ReentrantLock获取锁和释放锁过程
2022-02-09 11:49:06 0 举报
ReentrantLock获取锁和释放锁过程
作者其他创作
大纲/内容
此时队列状态
for(;;)循环判断
将当前节点设置为尾节点,并返回当前节点
true
parkAndCheckInterrupt()LockSupport.park(this);阻塞当前线程
判断state是否为0
setExclusiveOwnerThread(Thread.currentThread())设置自己为锁的拥有者
否,返回false
释放之前
傀儡节点
直接返回true
tailwaitStatus = 0
tryRelease(arg)尝试释放锁
前提:已经有线程占用了锁
返回false
lock.lock()
否
传递封装有当前线程的node
nonfairTryAcquire(acquires);非公平获取锁
AbstractQueuedSynchronizer static class Node; transient volatile Node head; transient volatile Node tail; volatole int state;
判断failed是不否为true
设置p的状态为为唤醒状态
不为空
获取锁
enq(node)将当前节点加入队列
将当前节点置空,并且设置为头节点
第一次执行这个方法会返回false将前一个节点的状态改成唤醒第二次是true
AQS队列
当前线程是否是锁的持有线程
将state在原来的基础上加1
释放锁的返回结果
setExclusiveOwnerThread(current);将自己设置为锁的拥有者并返回true
将持有锁线程设置为空,返回true
失败
headwaitStatus = 0
class ReentrantLock abstract static class Sync extends AbstractQueuedSynchronizer static final class NonfairSync extends Sync static final class FairSync extends Sync
前提:前一个线程要释放锁
lock.unlock()
进行循环的第一次,返回false第二次就返回true
判断头节点不为null头节点的waitStatus != 0
如果当前节点的前一个节点是头节点,也就是傀儡节点,并且强占锁成功
返回true
false
是
当前线程抢占锁成功
进行下一次循环
当前节点(thread)
tryAcquire(1)尝试获取锁
包含
判断当前线程是不是锁的拥有者线程
headwaitStatus = 1唤醒状态
arg = 1Node.EXCLUSIVE = nullstate = 1
sync.release(arg)
最终走finally
unparkSuccessor(head)唤醒队列中阻塞的线程
成功
判断p是否是头节点
acquire(1)获取锁
为空
如果当前线程是锁的持有线程,那么,会将state在原来的基础上加1,返回true
判断state == 0
Node volatile Node prev; volatile Node next; volatile Thread thread; Node nextWaiter; volatile int waitStatus = 0
空
tryRelease
state != 0
此时没有线程占用锁,将当前线程设置为锁的拥有者线程
addWaiter添加到等候队列将当前线程封装到Node里面
尾节点是否为空
抢占锁失败cancelAcquire(node)
尝试获取锁tryAcquire(1)
state == 0
将当前节点设置成为尾节点返回上一个尾节点傀儡节点
创建一个空节点,将空节点设置为头,将尾节点指向头节点
acquireQueued(node)
for(;;)循环判断,尾节点是不否为空
failed = trueinterrupted = false
获取当前节点的前一个节点,前节点不能为空,用p表示前节点
如果当前线程不是锁的持有线程,IllegalMonitorStateException。将state减1
0 条评论
回复 删除
下一页