AQS(AbstractQueuedSynchronizer)是一个使用FIFO队列实现的同步框架,通过提供对变量state的读写,实现线程间的同步,常见的同步类如ReentrantLock,CountDownLatch都依赖它实现。

实现原理

AQS内部维护了一个双向链表,每个节点引用了一个不同的线程,AQS内部也分别引用了头节点和尾节点。

获取锁时,首先尝试获取锁(通过CAS设置state值),如果不成功,则生成一个节点(其中引用了当前线程)加入同步队列队尾,然后自旋(死循环)。如果发现当前节点的前一个节点是头节点,那么会尝试获取锁,成功则返回;如果当前节点上一个节点不是头节点,则park当前线程直到被中断或唤醒

释放锁时,首先尝试释放锁,成功则唤醒下一个有效的节点

共享的获取和释放锁相对于独占共享和释放锁,多了一步再获取锁成功的情况下,同时通知后继节点获取锁的操作。

同步队列和等待队列

上面介绍的是同步队列的操作,比如lock,unlock等,对于获取锁之后需要等待并释放锁,然后等待其他线程唤醒的场景,我们使用的是Condition.await()和Condition.signal()方法。

对于await,由于调用此方法时线程已经获取了锁,会构造一个node引用当前线程加入等待队列,然后释放线程,等待signal的唤醒

而signal方法,就是将等待队列的节点移动到同步队列,然后等待释放锁的线程唤醒

参考

https://www.cnblogs.com/waterystone/p/4920797.html

https://www.cnblogs.com/zerotomax/p/8969416.html