ReentrantLock(AQS)流程图
2023-03-04 15:22:45 0 举报
ReentrantLock(AQS)流程图
作者其他创作
大纲/内容
否
do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0);
公平锁,本次唤醒后去获取锁必定能够成功。但是如果是非公平锁,就可能获取失败
是,将waitStatus从-1变更为0
waitStatus=0
thread=null
thread=T0
加入队列的(判断是否需要阻塞x线程)
getState()+1
next
tryAcquire(1)
tail
unlock();
node.predecessor()前置节点不为head || 获取锁失败
pred.waitStatus 0
死循环,自旋
parkAndCheckInterrupt())
当前是无锁状态
next=null
更新state状态
prev=null
ReentrantLock
阻塞线程,等待被唤醒
head
next=nll
获取锁
作为参数
setState(getState() - releases)
释放锁
第一个加锁线程-T0
//获取head节点的下一节点Node s = node.next;
node.predecessor()== head
waitStatus=0/-2/-3
获取AQS中锁标识
waitStatus=-1
pred.waitStatus > 0 ,只有一种情况那就是等于1(出现异常,中断引起,需要将出现的异常的节点剔除)
lock()
如果刚好获取锁成功,将head节点指向当前节点(成为新的head节点),prev =null,取先取消原本head节点的next=null
唤醒指定线程
current == getExclusiveOwnerThread()
原本的head节点被GC清除掉
因为是公平锁,判断是否有阻塞节点
unparkSuccessor(head);
return false获取锁失败
prev
获取锁成功,标识获取锁的线程为当前线程
获取锁过程失败,加入阻塞队列
setExclusiveOwnerThread(current);
释放锁的时候需要判断0
已经存在阻塞节点,获取锁失败,需要加入阻塞队列
new FairSync()
重新回到循环,再次执行
公平锁
是
有锁
(pred.waitStatus == Node.SIGNAL
getState()==0
第一次循环,初始化一个head节点,其waitStatus表示的是下一节点的生命状态
如果前一节点就是head,说明下个就是当前线程可以去获取锁了,为减少线程阻塞/唤醒的操作,优先尝试去获取锁
没有阻塞节点
addWaiter(Node.EXCLUSIVE)
唤醒后,重现回到循环处。尝试获取锁
head != null && h.waitStatus != 0
ws < 0
LockSupport.unpark(s.thread);
判断当前线程是否就是获取的线程(reentrantLock是重入锁)
将前置节点的waitStatus变更为-1(可唤醒状态)
***waitStatus表示的是下一节点的生命状态
尝试获取锁
tryRelease(arg)
hasQueuedPredecessors()
//前一节点的waitStatus=-1 =可被唤醒状态return true
收藏
0 条评论
下一页