AQS的执行过程
本文是参考了https://www.javadoop.com/post/AbstractQueuedSynchronizer 该篇博客,然后根据他写的思路将加锁的过程转化为流程图。
流程图不太标准。
加锁
解锁
释放的流程就不再画图,过程如下:
首先调用
release(1)
方法。该方法内部,会先调用
tryRelease(1)
方法。tryRelease方法中,会先判断当前线程是否是持有锁的线程,如果不是就返回异常,如果是,则判断释放一次锁后锁的标志位是否为0,如果为0则意味着没有重入,直接全部释放,否则不能完全释放。
如果调用
tryRelease(1)
成功,则会回到release方法中。后续会先获取到头节点,并判断状态,如果都没事,就唤醒后继节点。1
2
3
4
5
6if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}unparkSuccessor方法内部,会先判断头节点状态,如果不是0就改为0。之后获取后继节点,如果不为空,则唤醒,如果为空,则从队列的队尾从前遍历,将其中status小于0的设置为下一个待唤醒的线程。
细节
waitStatus 初始化为0,然后是后一个节点修改前一个节点的waitStatus 的值。一般都是改为-1。waitStatus 为-1表示的是后继节点需要唤醒。
即这个waitStatus 并不代表自身的状态,而是后继节点的状态。