AQS同步器源码分析
2018-07-24 17:08:33 0 举报
AQS同步器源码分析
作者其他创作
大纲/内容
Y
设置当前结点为head
s != null?
*共享模式下,自己拿到资源后如果尚有剩余资源,还会去唤醒后继线程(较独占模式的不同)
*安全结点:找到在当前结点前面的最近一个正常等待状态的结点并排在其后面,忽略掉中间的放弃状态(state0)的结点们
*有效结点:state=0
找到队列中最前面的有效结点s
设置前驱结点状态为SIGNAL
*等待被唤醒:unpark()或interrupt()
false
成功(r=0)
true,CAS成功
返回true结束
false,置零失败,自旋循环
N
acquire()开始
true
唤醒方式是否通过interrupt()?
unparkSuccessor()唤醒后继
tryAcquireShared(arg)
shouldParkAfterFailedAcquire()找安全结点
r=tryAcquireShared(arg)
*PROPAGATE传播失败
=
release()开始
addWaiter(Node.SHARED)加入等待队列尾部
判断h的状态waitStauts
首先尝试快速方式CAS直接入队,如果失败了再调用enq()通过CAS自旋的方式入队
失败,自旋
独占模式获取和释放资源
成功
tryAcquire()
唤醒结点线程LockSupport.unpark(s.thread)
h!=null && h!=tail?
被唤醒之后
false,CAS失败,自旋
SIGNAL(-1)
成功(=0)
前驱结点为head并且tryAcquire()成功?
r0?资源还有剩余?
线程获取资源成功
*arg: 资源数量
判断前驱结点为head?
doAcquireShared(arg)
CAS状态置零compareAndSetWaitStatus
结点状态置0compareAndSetWaitStatus
selfInterrupt()中断当前线程
失败(0)
addWaiter()加入等待队列尾部
doReleaseShared()唤醒后继线程
获取资源成功
selfInterrupt()中断当前线程,结束
0(执行过唤醒后继)
N,自旋
挂起线程LockSupport.park(this)
找到head结点(一般为当前结点)
N(自旋)
CAS状态设为PROPAGATE(-3)
tryRelease()
acquireShared(arg)开始
判断当前线程的唤醒方式是否是通过interrupt()?
返回false结束
releaseShared(arg)开始
当前结点设为head
h=head找到head结点(一般为当前结点)
设置前驱结点为SIGNAL
tryReleaseShared(arg)
共享模式获取和释放资源
0 条评论
下一页