高并发编程的成神之路--3.AbstractQueuedSynchronized(AQS)源码底层分析
AbstractQueuedSynchronized(AQS)详解
在研究一个类的时候先读它的原代码这样能有一个整体的认识(下面只是截取了部分,需要看的自己把后面的看完)
源码分析:
查看ReentrantLock类的lock()方法
可以看到它本身调用的是同步方法
由于存在公平锁和非公平锁
在这个里面存在着一个可重入锁的概念。
非公平锁:
还是一个之前手写可重入锁的概念,获取当前线程,修改状态值c,然后设置独占线程
在重入之后可以直接返回true继续执行,而不会锁死
如果拿到锁了,就不执行后面的,没拿到继续执行后面的语句
这里面就相比来说比较复杂
Node.EXCLUSIVE独占
就是一个链表,将进入的新的结点添加进去
enq()方法,当没有尾节点,那就将node作为尾节点存放
上面我们已经将所有等待的线程放入到等待双向链表中,但是并没有阻塞它
回到 acquireQueued()
如果当前结点(等待双向链表的尾节点)的前面一个结点是头结点,那就将它踢出去,将自己设置为头结点
如果当前双链表中存在三个及三个以上结点,执行下面的语句
如果为等待状态返回true
取消状态
移除掉取消状态的结点(判断的是node结点的前一个结点)
如果是小于0的,就将结点设置为等待
ShouldParkAfterFailAcquire()方法只有当结点是singal(等待状态的时候)返回true。
继续执行后面的
让当前线程真正处于等待状态
现在的话基本上加锁流程就结束了。
现在看解锁:
首先就是进行c的状态-1
如果当前线程不是独占线程(之前没有进行lock)
c其实就是一个计数器,记录当前线程拿了几个锁,拿一个锁(lock)+1,释放一个锁(unlock)-1
如果c为0说明就没有线程拿锁,就可以直接释放独占线程资源
回到release方法
有独占线程tryRelease就返回false,没有独占线程就返回true
头结点不为null,不等于0说明当前头结点为等待状态
这行来说意义不大,不需要研究
node的下一个结点为空,那就将尾节点赋给它的下一个结点
如果不为空,就叫醒当前结点上的线程去争夺CPU资源
总结:AQS主要是通过一条双向链表和一个状态值来维护的