AbstractQueuedSynchronizer源码分析(一)
1、父类:AbstractOwnableSynchronizer
在AbstractOwnableSynchronizer中只有一个属性和对其的get()和set()方法。
exclusiveOwnerThread:这个属性表明在独占模式下,拥有锁的线程。AOS和子类AQS并不会使用这个属性,而其子类可以在通过维护该属性来控制线程访问控制权。
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
/** 空构造函数供子类使用。 */
protected AbstractOwnableSynchronizer() { }
/** 独占模式,拥有同步状态的线程 */
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
2、AbstractQueuedSynchronizer的静态内部类Node
Node持有一个线程,并在表示该线程在同步器等待队列中的状态。直至其线程获得了锁,就会释放这个Node节点。
Node属性介绍
字段名称 | 类型 | 默认值 | 作用 |
---|---|---|---|
SHARED | Node | new Node() | 标识节点以共享模式等待 |
EXCLUSIVE | Node | null | 标识节点以独占模式等待 |
CANCELLED | int | 1 | 标识线程已经被取消 |
SIGNAL | int | -1 | 标识当前节点的后继节点的线程需要取消阻塞 |
CONDITION | int | -2 | 标识线程由于阻塞而处于等待状态 |
PROPAGATE | int | -3 | 标识处于共享状态下,下一次的acquire需要无条件地传播 |
waitStatus | int | 0 | 标识处于初始状态 |
prev | Node | null | 当前节点的前驱节点 |
next | Node | null | 当前节点的后继节点 |
Node方法介绍
方法名 | 返回值 | 作用 |
---|---|---|
isShared() | boolean | 判断该节点是否共享模式 |
predecessor() | Node | 获取当前节点的前驱节点 |
static final class Node {
/** 标识节点以共享模式等待 */
static final Node SHARED = new Node();
/** 标识节点以独占模式等待 */
static final Node EXCLUSIVE = null;
/** 标识线程已经被取消 */
static final int CANCELLED = 1;
/** 标识当前节点的后继节点的线程需要取消阻塞 */
static final int SIGNAL = -1;
/** 标识线程由于阻塞而处于等待状态 */
static final int CONDITION = -2;
/** 标识处于共享状态下,下一次的acquire需要无条件地传播 */
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
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
3、AbstractQueuedSynchronizer的基本数据结构
- AQS的基本数据结构以Node节点组成的等待队列,可以理解为“等待锁的线程队列”。
- 每个Node节点都持有一个“waitStatus”字段,用于标记线程当前的行为。
- head节点的下一个节点会尝试acquire,因为head节点是一个dummy节点,不持有线程。
- 入队操作是直接将节点加入队列尾部。
- 线程获取锁后,Node节点释放线程,并设置为head头结点。
下面图示表示了AQS的数据结构
4、AbstractQueuedSynchronizer的public方法初识
public修饰的方法是提供给同步工具类使用的,如ReentrantLock、ReentrantReadWriteLock等同步工具使用的。
方法 | 返回值 | 作用 |
---|---|---|
acquire(int arg) | void | 不响应中断的获取独占锁 |
acquireInterruptibly(int arg) | void | 响应中断的获取独占锁 |
tryAcquireNanos(int arg, long nanosTimeout) | boolean | //TODO |
release(int arg) | boolean | 释放独占锁 |
acquireShared(int arg) | void | 不响应中断的获取共享锁 |
acquireSharedInterruptibly(int arg) | void | 响应中断的获取共享锁 |
tryAcquireSharedNanos(int arg, long nanosTimeout) | boolean | //TODO |
releaseShared(int arg) | boolean | 释放共享锁 |
上面是对后面的内容进行铺垫,后续章节主要介绍锁是如何对同步状态进行管理。以上这个几个方法是获取同步状态和释放同步状态的核心方法。会逐一对其逻辑进行详细剖析。