每个 Java 工程师都应该或多或少地了解 AQS,我已经反复研究了很长时间,忘记了一遍又一遍地看它.每次我都有不同的经历.这一次,我打算重新拿出系统的源代码,并将其总结成一系列文章,以供将来查看.
一般来说,AQS规范是很难理解的,本次准备分五篇文章用来分析AQS框架:
本篇文章为系列文章的第二篇,本篇文章先介绍一下AQS内部属性字段和内部类等,让我们更方便看懂代码
通过第一篇文章我们已经知道,AbstractQueuedSynchronizer 是其他同步器的基础类,它被用来实现阻塞锁和依赖先进先出(FIFO)等待队列的相关同步器(例如,互斥锁(ReentrantLock)、读写锁(ReentrantLock)、信号量(Semaphore)、屏障(CyclicBarrier)、Futures等),它的内部依赖于单个原子int值来表示同步状态。
子类必须定义更改此状态的受保护方法,以及定义此状态在获取或释放此对象方面的含义。这个类中的其他方法执行所有排队和阻塞机制。子类可以维护其他状态字段,但是只有使用getState()、setState(int)和compareAndSetState(int,int)方法操作的原子更新的int值被跟踪到同步。
// 等待队列的头
private transient volatile Node head;
// 等待队列的尾
private transient volatile Node tail;
// 同步状态
private volatile int state;
// 自旋锁阈值
static final long spinForTimeoutThreshold = 1000L;
static final class Node {
// 用于标识节点正在共享模式下等待的标记
static final Node SHARED = new Node();
// 用于标识节点正在独占模式下等待的标记
static final Node EXCLUSIVE = null;
// waitStatus值,标识线程已取消
static final int CANCELLED = 1;
// waitStatus值,用于标识后续线程需要唤醒(unparking)
static final int SIGNAL = -1;
// waitStatus值,标识线程正在等待条件
static final int CONDITION = -2;
// waitStatus值,表示下一个acquireShared(共享同步状态获取)应该无条件传播
static final int PROPAGATE = -3;
// 当前节点状态
volatile int waitStatus;
// 前节点
volatile Node prev;
// 后节点
volatile Node next;
// 当前节点线程
volatile Thread thread;
// 节点类型/
Node nextWaiter;
// 是否是共享模式
final boolean isShared() {
return nextWaiter == SHARED;
}
// 获取前节点
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
// 只能用于 addWaiter
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
// 只能用于Condition
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
通过Node 节点字段SHARED与EXCLUSIVE,节点有两种模式
// 尝试以独占模式获取。此方法应查询对象的状态是否允许在独占模式下获取它,如果允许,则获取它。
protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException();}
// 尝试设置状态以反映独占模式下的释放
protected boolean tryRelease(int arg) { throw new UnsupportedOperationException();}
// 尝试在共享模式下获取。此方法应查询对象的状态是否允许在共享模式下获取该对象,如果允许,则获取该对象。
protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();}
// 尝试设置状态以反映共享模式下的释放。
protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException();}
//如果以独占方式针对当前(调用)线程保持同步,则返回TRUE。此方法在每次调用非等待AbstractQueuedSynchronizer.ConditionObject方法时调用。(等待方法改为调用Release。)
protected boolean isHeldExclusively() { throw new UnsupportedOperationException();}
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizerImitate.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizerImitate.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizerImitate.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
/**
* CAS head field. Used only by enq.
* CAS 设置 头结点字段 仅供enq使用。
*/
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
/**
* CAS tail field. Used only by enq.
* CAS 设置 尾结点字段 仅供enq使用。
*/
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
/**
* CAS waitStatus field of a node.
* CAS 设置 waitStatus字段。
*/
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
/**
* CAS next field of a node.
* CAS 设置 节点的下一个字段。
*/
private static final boolean compareAndSetNext(Node node, Node expect, Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}