ReentrantLock 公平锁加锁流程图
2023-03-21 20:24:59 0 举报
ReentrantLock 公平锁加锁流程图
作者其他创作
大纲/内容
thread=t3
是
CAS head为new Node()
waitStatus=0
将tNode设为head,将tNode的thread和prev设为nullhead原先指向的node会被GC
HEAD
成功
prev
thread=t1
thread=thread4prev=nullnext=null
waitStatus=-1
next
CAS将tNode设为tail
否
waitStatus=1
CAS为state+1成败
thread=null
thread=tNode
编号5
true/false
thread=t2
Node t=tail判断t是否为空
是第一个,要再自旋一次尝试获取锁tryAcquire()
判断p的waitStatus是否==0
无排队状态
创建当前线程的Node:tNode
给p节点的waitStatus赋值为-1
当前队列一定为空(对应下方编号2)
enq(tNode)
编号0
继续循环
TAIL
编号2
p = p.prev;node.prev =p;跳过所有cancel状态的节点
HEAD&TAIL
tNode
判断是否需要排队hasQueuedPredecessors()
将head赋值给tailtail=head
有另一个专门兼容线程Interupt的加锁方法——lockInterruptibly,关于shouldParkAfterFailedAcquire、parkAndCheckInterrupt 方法和acquireQueued方法中,Thread.Interupt()的逻辑,在lock方法里可以完全忽略。该逻辑仅在使用lockInterruptibly加锁时有用。
等待队列结构概览
判断lock的state是否为0
tail
prev=null
如下方编号0中的t3,waitStatus为1
此时tNode一定是tail了
判断p的waitStatus是否为-1
Node pred=tail判断pred是否为空
加锁成功设置exclusiveOwnerThread为当前线程
将前一个节点指向tNodepred=tNode.prev
false
编号1
t.next=tNode
编号4
第一个排队线程添加完成后
Node p=tNode.prev判断p是否为head
加锁失败
编号3
拿到锁之后,释放node
tNode.prev=tail
null
tNode.prev=tt.next=tNode
acquireQueued(tNode)
第一次新增排队线程
失败
放置队列末尾(对应下方编号2345)
判断当前锁的exclusiveOwnerThread是否为当前线程
是即此线程是第一个排队的
shouldParkAfterFailedAcquire(p,tNode)
当前队列一定为空(对应下方编号1)
tryAcquire()thread4
LockSupport.park(this)当前线程开始阻塞
true
addWaiter()
此时线程尚未park
被unpark
0 条评论
下一页