ReentrantLock之 Lock 加锁过程
2022-11-01 08:33:40 0 举报
ReentrantLock之 Lock 加锁过程
作者其他创作
大纲/内容
true
这个队列表示,在节点n2插入队列之前,没有其他节点在排队注意,当前持有锁的线程,永远不会处于排队队列中,这是因为:当一个线程调用lock获取锁时,只有两种情况:1)锁处于自由状态(state == 0),且它不需要排队,通过cas立刻获取到了锁,这种情况,显然它不会处在排队队列中;2)锁处于非自由状态,线程加入到了排队队列的对头(不包含head)等带锁。将来某一时刻,锁被其他线程释放,并唤醒这个排队的线程,线程唤醒后,执行tryAcquire,获取到了锁,然后重新维护排队队列,将自己从队列中移除(acquireQueued方法)。所以,不管哪种情况,持有锁的线程,永远不会处于排队队列中。
FairSync# lock()
parkAndChecklnterrupt线程进入阻塞状态
tryAcquire
3
sync继承了 AbstractQuenedSynchronizer
CAS获取锁
false
sync.lock( )
acquireQueued返回,表示线程获取到锁,线程逐级返回,加锁过程结束
返回true, 表示获取到了锁,线程逐级返回,加锁过程结束
acquire(1)
两种情况,会导致阻塞结束:1、持有锁的线程,释放锁后,将这个线程unpark了。此时该线程,一定排在队列的队头(不包括head节点);2、线程被interrupt了。(注意,在外部interrupt这个线程,不是抛出interruptException,这一点和sleep、wait、阻塞不一样)
队列已经初始化,将node加入到队列末尾,加入后队列可能如下
公平锁
true,执行上图步骤1
ReentrantLock
pred.waitState > 0?
返回false,表示线程没有获取到锁
acquireQueued
返回node
lock
NonFairSync# lock()
false再次循环判断
阻塞结束
addWaiter详解
返回 false
非公平锁,默认
false(即 ==0)
没有其他线程在排队,调用enq构造队列,并将node加入到队列
shouldParkAfterFailedAcquire方法详情
p == head?表示查询 node是不是第一个排队的
pred.waitState == Node.SIGNA( -1) ?
再次循环判断
这部分,是node加入队列后的处理逻辑,这里会有一次自旋,尝试获取锁,获取不到,才调用park 阻塞自己
abstract void lock()
将当前线程封装成Node对象,并加入排队队列中。根据排队队列是否执行过初始化,执行 1、2不同处理逻辑。1:表示排队队列不为空,即之前已经初始化过了,此时只许将新的node加入排队队列末尾即可。2:表示排队队列为空,虚执行队列初始化,enq会初始化一个空的Node,作为排队队列的head,然后将需要排队的线程,作为head的next节点插入。
返回 true
pred != null
enq方法
成功获取到锁,设置锁持有线程为当前线程,返回
addWaiter
acquireQueued方法详解
执行排队逻辑
表示获取到锁:1、node设置为头结点2、释放之前的头结点这个逻辑执行完成后,node节点就不在排队了(获取到锁的线程,不会在排队队列中了)
执行park逻辑
0 条评论
下一页