本文基于JDK1.8
本篇学习目标
了解AQS的设计思想以及重要字段含义,如通过state字段表示同步状态等。
了解AQS内部维护链式双向同步队列的结构以及几个重要指针。
了解五种重要的同步状态。
明确两种模式:共享模式和独占模式。
学习两种模式下AQS提供的模板方法:获取与释放同步状态相关方法。
了解Condition、ConditionObject等AQS对条件变量的支持。
通过Condition的案例深入了解等待通知的机制。
AQS概述
AQS即AbstractQueuedSynchronizer,队列同步器,他是构建众多同步组件的基础框架,如ReentrantLock、ReentrantReadWriteLock等,是J.U.C并发包的核心基础组件。
AQS框架基于模板方法设计模式构建,子类通过继承它,实现它提供的抽象方法来管理同步状态。
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
// 序列化版本号
private static final long serialVersionUID = 7373984972572414691L;
/**
* 创建AQS实例,初始化state为0,为子类提供
*/
protected AbstractQueuedSynchronizer() { }
/*---------------- 同步队列构成 ---------------*/
// 等待队列节点类型
static final class Node {
//...省略
}
/**
* 除了初始化之外,它只能通过setHead方法进行修改。注意:如果head存在,它的waitStatus保证不会被取消
*/
private transient volatile Node head;
/**
* 等待队列的尾部,懒初始化,之后只在enq方法加入新节点时修改
*/
private transient volatile Node tail;
/*---------------- 同步状态相关 ---------------*/
/**
* volatile修饰, 标识同步状态,state为0表示锁空闲,state>0表示锁被持有,可以大于1,表示被重入
*/
private volatile int state;
/**
* 返回当前同步状态
*/
protected final int getState() {
return state;
}
/**
* 设置同步状态
*/
protected final void setState(int newState) {
state = newState;
}
/**
* 利用CAS操作更新state值
*/
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
static final long spinForTimeoutThreshold = 1000L;
// 这部分和CAS有关
// 获取Unsafe实例
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 记录state在AQS类中的偏移值
private static final long stateOffset;
static {
try {
// 初始化state变量的偏移值
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
} catch (Exception ex) { throw new Error(ex); }
}
}
以上包括AQS的基本字段,比较核心的就是两个部分:
内部FIFO队列的节点类型Node,和首尾指针字段。
同步状态相关的方法,设置,获取,CAS更新等。
接下来我们将一一学习这些内容。
AbstractOwnableSynchronizer
AbstractQueuedSynchronizer继承自AbstractOwnableSynchronizer,它提供了设置或获取独占锁的拥有者线程的功能。
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
// 本身是抽象类,该构造方法实为为子类提供
protected AbstractOwnableSynchronizer() { }
/* 互斥模式同步下的当前线程 */
private transient Thread exclusiveOwnerThread;
/* 设置当前拥有独占访问的线程。锁的拥有线程,null 参数表示没有线程拥有访问。
* 此方法不另外施加任何同步或 volatile 字段访问。
*/
protected final void setExclusiveOwnerThread(Thread t) {
exclusiveOwnerThread = t;
}
/* 返回由 setExclusiveOwnerThread 最后设置的线程;
* 如果从未设置,则返回 null。
* 此方法不另外施加任何同步或 volatile 字段访问。
*/
p