ReentrantLock源码
2021-08-18 10:00:56 5 举报
ReentrantLock
作者其他创作
大纲/内容
LockSupport.unpark(s.thread)
前驱节点不是head或竞争锁没有成功
结束
pre
next
Node h = head
lock()
在队列当中的Thread节点,准备阻塞等待获取锁
extends Sync
state减1,减到0时锁的Thread属性置空
nodetail
unlock解锁
从队尾往前找,找到waitStatus<=0的所有节点中排在最前面的这样不必担心中间有节点取消(waitStatus==1)的情况
获取锁
h != null && h.waitStatus != 0
首先cas 更新 state值公平锁没有这一步
p = node.predecessor()获取node前驱节点
ReentrantLock
new FairSync()
返回true
for (;;) 自旋操作
p == head && tryAcquire(arg)
唤醒线程
成功获取锁成 设置当前thread
尝试加锁失败当前线程构建成一个Node放到阻塞队列中CLH
acquire(1)
tryAcquire(arg)
new NonfairSync()
如果返回true并把当前线程挂起
addWaiter(Node.EXCLUSIVE)
selfInterrupt()
1.如果当前入队节点的前驱节点是head,说明它是阻塞队列的第一个,所以当前节点可以去试抢一下锁。head一般指的是占有锁的线程,head后面的才称为阻塞队列2.如果尝试加锁成功,就更新head=node,然后之前的head.next=null助于GC3.如果前驱节点不是head或竞争锁没有成功
公平模式
unparkSuccessor(h)
head
AbstractQueuedSynchronizer
获取CLH的head
true
1.先判断下前驱节点的waitStatus值,如果是-1,说当前驱节点的线程正常,没有中途取消排队,则需要挂起当前线程,等待以后唤醒,调用LockSupport.park(this)2.如果驱节点 waitStatus>0则表示前驱节点取消了排队,则要给当前节点重新找一个没有取消排队的前驱节点关联上,因为线程的唤醒都是依赖正常的前驱节点。3.以上条件都不满足,CAS将前驱节点的waitStatus设置为-14.发现其实第一次进来的时,前驱节点的waitStatus是0,因为初始化head时就是0,经过一轮循环后,后继节点才可以把前驱接的waitStatus设为-1,然后才可能会挂起当前进队队列的线程节点。(一般不是队头节点的情况)
setExclusiveOwnerThread(Thread.currentThread())
sync.release(1)
非公平模式默认
node
0 条评论
回复 删除
下一页