一、AQS的介绍
队列同步器(AbstractQueuedSynchronizer)简称AQS,是JUC同步构件的基础,包括ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphor都是基于AQS实现的。
理解AQS是理解这些同步工具的基础,基于AQS提供的同步语义可以定制各种功能的同步工具。
二、AQS原理
1、用一个int类型的状态变量(volatile)state记录同步状态,默认值是0
2、用一个双向链表实现的队列对线程进行排队和调度
3、A线程使用compareAndSet(state,0,1)原子设置state的值,设置成功说明state当前无其他线程争用,A线程取得锁的使用权。
4、设置不成功,说明B线程对state的值进行了设置,并且没有复位(state!=0),B线程持有锁的使用权(B线程还没有释放锁)。A线程会构造成一个Node节点加入队列尾部并挂起。
5、当B线程执行完同步操作后,对state进行复位(state==0),即释放锁,然后从队列头开始寻找,发现正在沉睡的A线程,将其唤醒。
三、AQS同步队列(双向链表实现的队列)
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
static final class Node {
/**共享模式 */
static final Node SHARED = new Node();
/**独占模式 */
static final Node EXCLUSIVE = null;
/**取消状态,由于在同步队列中等待的线程等待超时或被中断,
* 需要从同步队列中取消等待。
*/
static final int CANCELLED = 1;
/**通知状态,当前节点的后继节点包含的线程需要运行(unpark)
* 当前节点的线程如果释放了同步状态或者被取消,将通知后续节点。
*/
static final int SIGNAL = -1;
/**条件阻塞状态,节点线程等待在Condition上,
* 当其他线程对Condition调用了signal()方法后,
* 该节点将会从等待队列中转移到同步队列中,
* 加入到对同步状态的获取中。
*/
static final int CONDITION = -2;
/**传播状态,表示当前场景下后续的acquireShared能够得以执行。*/
static final int PROPAGATE = -3;
/**节点的的状态