AbstractQueuedSynchronizer(AQS)互斥锁的获取
2022-05-02 14:51:30 0 举报
Java AQS 互斥锁获取(锁定)流程图
作者其他创作
大纲/内容
当前节点的后继节点状态是取消?
no
获取当前节点的前驱节点
成功获取到互斥锁
yes
返回true表明线程通过中断唤醒设置为中断为为true
返回节点node
是否发生异常?
前驱节点引用线程是否为空?
调用acquireQueued(node)
尾插法插入队列
返回是否true?
调用selfInterrupt()自行中断
将当前node设置为头节点head
true允许阻塞
判断当前节点是否尾节点?
尝试获取锁失败?
tryAcquire(arg)抽象方法,由子类实现
获取当前节点的后继节点
true
获取其后继节点
成功取消锁获取流程
返回true表示当前线程可以阻塞
修改前驱节点的后续为新找到的状态不大于0的节点
public final void acquireInterruptibly(int arg)获取互斥锁,响应中断,抛出中断异常参数为1用来操作state变量
小结:和acquire方法没有多大区别,区别在于1、acquireInterruptibly方法响应了中断,抛出中断异常,线程不继续获取锁。2、而acquire方法忽略中断即中断可以唤醒并设置和返回中断标志位
结束
进入下一次循环(死循环等待)
前驱节点状态是否为Node.SIGNAL?或者
第一次尝试获取锁(由子类实现尝试获取锁的流程)
public final void acquire(int arg)获取互斥锁,忽略中断,将中断状态位返回给上层参数为1用来操作state变量
CAS操作是否成功?
前驱节点为头节点?
false不允许阻塞
是否为Node.SIGNAL
获取当前节点前驱状态不为取消的节点
调用parkAndCheckInterrupt()将当前线程设置为可中断的等待
CAS替换其前驱节点为尾节点(非取消状态)
循环查询下一个状态不大于0的节点
取消获取锁流程
开始
释放前一个节点成功获取锁
线程是否中断
是否中断
创建Node对象,保存当前线程的引用
前驱节点状态CAS设置为SIGNAL是否成功?
创建Node节点并插入竞争队列
Node addWaiter(Node mode)
获取前驱节点的状态waitStatus
返回false表示当前线程不可park阻塞
调用cancelAcquire(node)
取消锁获取流程
尝试获取锁成功?
抛出异常
释放当前节点引用的线程对象(node的线程引用设置为空)
返回中断标识false表示线程在等待过程中没有产生中断
无限循环等待
前驱节点非取消?
将前驱节点的next设置为该后继节点
将当前节点状态设置为Node.CANCEL取消
判断状态是否大于0(是否取消Node.CANCEL)
判断当前节点是否为空?
小结:一、阻塞的条件:确保当前节点的前驱节点状态有Node.SIGNAL则可以放心阻塞否则不允许阻塞二、无限循环结束条件:当前等待节点为头节点,并且成功获取到锁三、发生异常的时候:执行取消锁获取流程
将前驱节点的后继next指针设置为空
表明前驱节点会唤醒后续节点所以当前节点可以放下阻塞
调用unparkSuccessor(node)唤醒后继节点
修改前驱节点状态为SIGNAL
快速插入等待队列中,CAS替换尾指针tail
调用doAcquireInterruptibly(int arg)以响应中断方式获取锁
前驱节点是否为头节点?
enq(node)死循环插入,CAS替换尾指针原子性插入Node节点直到插入成功退出
前驱节点为头节点,则需要唤醒后继节点
判断当前节点是否允许park阻塞等待
0 条评论
下一页