AQS
(AbstractQueuedSynchronizer)是JUC
(java.util.concurrent)locks包中的实现锁的基础。
它提供一个依赖于FIFO的等待队列,实现阻塞锁和相关同步器(信号量,事件等)的框架。依赖单个原子的int值,旨在成为大多数同步器的有用基础。
该类支持默认独占模式和共享模式之一或两者。在独占模式下获取时,其他线程尝试获取不能成功。多个线程获取的共享模式可能(但不一定)成功。
API中已经给出了详细的描述,AQS使用队列实现,并且使用int类型的值代表锁的状态。锁分为独占、共享两种类型。locks包下还有一个使用long来标识状态的实现,细节跟AQS一致。下面是它的实现类

AbstractQueuedSynchronizer类中需要子类实现的方法都已经列出:
- tryAcquire,尝试获取独占锁
- tryRelease,尝试释放独占锁
- tryAcquireShared,尝试获取共享锁
- tryReleaseShared,尝试释放共享锁
- isHeldExclusively,当前线程是持有独占锁
在ReentrantLock
和ReentrantReadWriteLock
中都分别实现了上面的方法。后面我会详细分别在其中的实现方式。
AQS使用队列实现,在代码中可以看到一个Node
的静态内部类,它持有到前一个和后一个Node的引用。Node分为SHARED
和EXCLUSIVE
两种类型。包含一个waitStatus
等待状态,通过CAS改变它的值。有以下几种状态:
- 0 默认值,正常的同步节点。
- CANCELLED = 1,Node由于超时或中断取消。节点永远不会离开这个状态。特别是,具有已取消节点的线程永远不会再次阻塞。
- SIGNAL = -1,该节点的后续节点是阻塞的,所以当前节点在释放和取消时需要解除后继节点的阻塞。
- CONDITION = -2,该节点当前在条件队列,在转换之前,status变成0,将不会使用同步队列节点。
- PROPAGATE = -3,releaseShared应该传播到其他node,在doReleaseShared中设置(仅限头节点)以确保继续传播,即使其他操作已经介入。
在AQS中持有head
和tail
Node节点,从而持有真个队列。
存在另一个内部类ConditionObject
实现Condition
接口,Condition实现类似于Object类的wait、notify方法,也是通过队列实现,在类内部持有firstWaiter
和lastWaiter
Node节点。
LockSupport是锁实现中实现线程阻塞的基础。
以上是java.util.concurrent.locks包中核心类,后面我们会针对具体实现深入分析代码的实现。