AbstractQueuedSynchronizer概述
-
该类的目的
1.1 按照官方文档的意思,该类是为实现阻塞锁和相关的同步器提供了一个框架,直白了说,就是提供了一个基础,这些同步器底层依赖于一个先入先出队列(FIFO) -
类成员介绍
2.1 FIFO队列节点成员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; static final int PROPAGATE = -3; volatile int waitStatus; volatile Node prev; volatile Node next; volatile Thread thread; Node nextWaiter; /** * Returns true if node is waiting in shared mode. */ final boolean isShared() { return nextWaiter == SHARED; } /** * Returns previous node, or throws NullPointerException if null. * Use when predecessor cannot be null. The null check could * be elided, but is present to help the VM. * * @return the predecessor of this node */ 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; }
}
2.2 ConditionObject内部类
Condition与Lock配合可以完成等待通知机制,和Object的wait和notify/notify等待/通知机制差不多,只不过后者是java底层级别的,前者是语言级别的。
firstWaiter 和 lastWaiter是条件队列的头尾指针,条件队列是一个单向链式队列,条件队列中node节点的waitStatu是 CONDITION = -2
如图中nextWaiter就是指向下一个等待节点的指针
2.2.1 ConditionObject的await()方法
public final void await() throws InterruptedException {
//如果当前线程处于中断状态,抛出中断异常
if (Thread.interrupted())
throw new InterruptedException();
//把当前线程封装为node节点, 加入到等待队列末尾
Node node = addConditionWaiter();
// 释放当前线程所占用的lock,在释放的过程中会唤醒同步队列中的下一个未取消的节点,即
//如果有被取消的节点则过滤掉,查询未被取消的节点
int savedState = fullyRelease(node);
int interruptMode = 0;
//如果当前节点还未在同步队列上,让当前线程进入等待状态
while (!isOnSyncQueue(node)) {
//停止当前线程,传入的同步对象是ConditionObject对象
//其中参数是用来标识当前线程在等待的对象
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}