ReentrantLock中的AQS流程
2020-12-10 16:48:02 23 举报
ReentrantLock中的AQS流程
作者其他创作
大纲/内容
没有等待线程
没有被线程占用state == 0
有等待的队列
在CLH队列中尝试获取锁
队列中有等待的线程
设置持有Sync对象的线程为null
tryAcquire
循环移除CLH中当前Node以及其之前连续的状态为CANCELLED的Node
返回false
继承
判断当前线程所属节点的前驱节点的等待状态pred.waitStatus
从tail节点开始往前遍历,找到最前边的waitStatus小于等于0的Node
否
其他状态(0|-2|-3)
找到了对应的node
acquire()
sync
设置独占Sync的线程为当前线程
尝试获取锁tryAcquire()
最新的状态是否为0c == 0?
FairSync
不为null
acquireQueued()
保证CLH队列中所有的Node的waitStatus为-1;只会有head中的waitStatus会在0 | -1 之间切换;每一个Node的waitStatus由后继节点对应的线程保证
计算新的statec = getState() - releases设置statesetState(c)
添加成功
当前Node因为超时或中断被取消
返回true
返回当前线程是否中断
为null
已初始化
获取到了锁
addWaiter()
获取锁compareAndSetState(0,acquire)
getState()获取Sync对象状态
lock
添加当前队列到CLH队列的尾部
不是CLH队列中的第一个节点
判断CLH队列(同步等待队列)中是否有等待的线程hasQueuedPredecessors()
尚未初始化
设置Sync对象中exclusiveOwnerThread为当前线程
获取到锁
是
tryRelease()
重复执行for循环
添加当前线程到CLH队列的尾部
当前线程自我了结selfInterrupt()
返回当前线程对应的Node对象
unlock
撤销CLH队列中某一个Node的对应线程的阻塞unparkSuccessor(head)
队列是否初始化tail == null?
CANCELLED(1)
类
尝试获取锁成功
将当前线程对应Node从CLH队列中移除
被线程占用state != 0
没有获取到锁
返回true,让当前线程被阻塞
2.添加当前线程到CLH队列中独占模式
判断当前线程是否是持有当前锁的线程current == getExclusiveOwnerThread()
release(1)
解除线程的阻塞
添加失败
方法
如果当前Node为队列中的第一个节点node.oredecessor() == head?
这里的等于0的情况是针对Node为LCH的tail的情况
添加当前线程到队列中enq(Node)
表示当前线程可以安全的进行阻塞
Sync当前是否被线程占用state = 0?
h != null && head.waitStatus !=0
初始化CLH队列(设置head和tail不为null)compareAndSetHead(new Node())
当前线程已中断
没有抢到锁的使用权
尝试获取锁失败
1.如果Sync对象没有被线程持有,且当前线程中没有等待的线程,则直接获取锁2.如果Sync被线程持有且是持有线程是当前线程,则修改Sync对象的state属性
SIGNAL(-1)
ReentrantLock
同步队列中有等待的线程tail != null
阻塞当前线程并判断当前线程是否在中断parkAndCheckInterrupt()
取head后的一个NodeNode s = node.next
1.尝试获取锁
NonfairSync
应该阻塞
修改Sync对象的state值nextc = c + acquire;setState(bextc)
0 条评论
下一页