AQS源码解析流程图
2022-01-09 22:29:42 0 举报
AQS源码解析流程图笔记,源自于周阳老师的AQS详解课程
作者其他创作
大纲/内容
false
已经初始化
h!=t返回false
acquireQueued()方法详解
CAS获取锁
判断之前确认是不是当前线程获取到锁
队列元素等于1
是
tryAcquire(arg)
设置pred.waitState = -1
返回node
ReentrantLock
sync.lock();
hasQueuedPredecessors()
true
阻塞结束
tryAcquire()方法执行流程详解
执行park逻辑
acquireQueued返回,表示线程获取到锁,线程逐级返回,加锁过程结束。
pred.waitState ==Node.SIGNAL(-1)?
s.thread != Thread.currentThread()
==0表示锁为自由状态
返回true
整个ReentrantLock的加锁过程,可以分为三个阶段:1、尝试加锁;2、加锁失败,线程入队列;3、线程入队列后,进入阻塞状态。对应下面①②③三部分。
p== head ?表示查询node是不是第一个排队的
这个队列表示,在节点n2插入队列之前,没有其他节点在排队。注意,当前持有锁的线程,永远不会处于排队队列中。这是因为:当一个线程调用lock获取锁时,只有两种情况:1)锁处于自由状态(state==0),且它不需要排队,通过cas立刻获取到了锁,这种情况,显然它不会处于排队队列中;2)锁处于非自由状态,线程加入到了排队队列的队头(不包括head)等待锁。将来某- -时刻,锁被其他线程释放,并唤醒这个排队的线程,线程唤醒后。执行tryAcquire.获取到了锁,然后重新维护排队队列,将自己从队列移出(acquireQueued方法)。所以,不管哪种情况,持有锁的线程,永远不会处于排队列表中。
acquire(1);
表示获取到锁:1. node设置为头结点2、释放之前的头结点这个逻辑执行完成后,node节点就不再排队了(获取到锁的线程,不会在排队队列中了)
公平锁
元素个数>1
返回flase
tryAcquire方法,尝试获取锁。以下几种情况,会导致获取锁失败:1、锁已经被其他线程获取;2、锁没有被其他线程获取,但当前线程需要排队:3、cas失败可能过程中已经有其他线程拿到锁了)锁为自由状态(c==0),并不能说明可以立刻执行cas获取锁,因为可能在当前线程获取锁之前,已经有其他线程在排队了,必须遵循先来后到原则获取锁。所以还要调用hasQueuedPredecessors方法,查看自己是否需要排队。
getState()==0?
addWaiter()方法详解
lock
shouldParkAfterFailedAcquire()方法详解
设置重入锁计数器
整个aqs的核心和难点之一。注意这里使用了for()首先判断node的前辈节点,font color=\"#ff0000\
返回false
addWaiter()
否
执行排队逻辑
FairSync#lock()
!=0表示不是自由状态
enq()方法
NonfairSync#lock()
尝试获取锁,如果获取不到,排队(阻塞当前线程)
1
false则再次刷新
成功获取到锁,设置锁持有线程为当前线程。返回
队列是否初始化?
acquireQueued()
队列元素>1
abstract void lock();
pred.waitState> 0?
这个队列表示,在线程C进入之前,已经有一个线程在排队获取锁了。
hasQueuedPredecessors()方法执行流程详解
3
false(即==0)
parkAndCheckInterrupt()线程进入阻塞状态
再次循环判断
非公平锁
重入锁的实现原理
尝试获取锁
判断在当前线程前面,是否已经有其他线程在排队了,有,则表示当前线程也需要排队
没有
pred!=null
2
收藏
0 条评论
回复 删除
下一页