前两篇文章别离介绍了 AQS 框架中的独占模式和共享模式,本篇将介绍 AQS 对 Condition 接口的实现。
在浏览本篇之前,倡议先理解 AQS 中的数据结构和独占模式的实现原理。

JUC 通过 Lock 和 Condition 两个接口实现管程(Monitor),其中 Lock 用于解决互斥问题,而 Condition 用于解决同步问题,而 AQS 对 Lock 和 Condition 接口的实现提供了一个根底的框架。

1. Condition 接口

Lock 代替了 synchronized 办法和语句的应用,Condition 代替了 Object 监视器办法的应用。

Condition 实现能够提供不同于 Object 监视器办法的行为和语义,比方受保障的告诉排序,或者在执行告诉时不须要放弃一个锁。
如果某个实现提供了这样非凡的语义,则该实现必须记录这些语义。

办法摘要:

// 造成以后线程在接到信号或被中断之前始终处于期待状态。 void await() // 造成以后线程在接到信号、被中断或达到指定等待时间之前始终处于期待状态。 boolean await(long time, TimeUnit unit) // 造成以后线程在接到信号、被中断或达到指定等待时间之前始终处于期待状态。long awaitNanos(long nanosTimeout) // 造成以后线程在接到信号之前始终处于期待状态。void awaitUninterruptibly() // 造成以后线程在接到信号、被中断或达到指定最初期限之前始终处于期待状态。 boolean awaitUntil(Date deadline) // 唤醒一个期待线程。void signal() // 唤醒所有期待线程。void signalAll() 

Condition 实质上是一个队列(称为条件队列),线程期待某个条件成立时,在队列中阻塞,直到其余线程查看条件成立起初告诉它。
对于同一个锁,只会存在一个同步队列,然而可能会有多个条件队列,只有在应用了 Condition 才会存在条件队列。

AQS 中对条件队列的应用:

当线程获取锁之后,执行 Condition.await() 会开释锁并进入条件队列,阻塞期待直到被其余线程唤醒。
当其余线程执行 Condition.signal() 唤醒以后线程时,以后线程会从条件队列转移到同步队列来期待再次获取锁。
以后线程再一次获取锁之后,须要在 while 循环中判断条件是否成立,若不成立需从新执行 Condition.await() 去期待。

2. Condition 应用

Condition 实例本质上被绑定到一个锁上。要为特定 Lock 实例取得 Condition 实例,请应用其 newCondition() 办法。

Java 官网文档提供 Condition 接口的应用示例:

对于一个有界阻塞数组,当数组非满时才能够往数组中存放数据,否则阻塞;当数据非空时才能够往数组中取元素,否则阻塞。

class BoundedBuffer {    final Lock lock = new ReentrantLock();    final Condition notFull = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];    int putptr, takeptr, count;    // 生产者办法,往数组外面写数据    public void put(Object x) throws InterruptedException {        lock.lock();        try {            while (count == items.length)                notFull.await(); // 阻塞直到非满            items[putptr] = x;            if (++putptr == items.length) putptr = 0;            ++count;            notEmpty.signal(); // 告诉非空        } finally {            lock.unlock();        }    }    // 消费者办法,从数组外面拿数据    public Object take() throws InterruptedException {        lock.lock();        try {            while (count == 0)                notEmpty.await(); // 阻塞直到非空            Object x = items[takeptr];            if (++takeptr == items.length) takeptr = 0;            --count;            notFull.signal(); // 告诉非满            return x;        } finally {            lock.unlock();        }    }}

在 JDK 的实现中,独占模式才可应用 Condition,共享模式不反对 Condition。
因为 AQS 的外部类 ConditionObject 只反对独占模式。

java.util.concurrent.locks.ReentrantLock.Sync#newCondition

final ConditionObject newCondition() {    return new ConditionObject();}

java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock#newCondition

public Condition newCondition() {    return sync.newCondition();}

java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock#newCondition

/** * Throws {@code UnsupportedOperationException} because * {@code ReadLocks} do not support conditions. * * @throws UnsupportedOperationException always */public Condition newCondition() {    throw new UnsupportedOperationException();}

3. Condition 期待办法

3.1 Condition#await

代码流程:

  1. 判断线程是否被中断,如果是,间接抛出InterruptedException,否则进入下一步
  2. 将以后线程封装为节点,存入条件队列。
  3. 开释以后线程已取得的全副的锁,若无持有锁则抛异样。
  4. 在条件队列中,阻塞以后节点。
  5. 以后节点从阻塞中被唤醒(signalled or interrupted),则会从条件队列转移到同步队列(被动或被动地)。
  6. 在同步队列中,自旋、阻塞期待获取锁胜利。
  7. 判断整个过程中是否产生过中断,进行不同的解决(抛异样 或 从新中断)。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#await()

/** * Implements interruptible condition wait. * <ol> * <li> If current thread is interrupted, throw InterruptedException. * <li> Save lock state returned by {@link #getState}. * <li> Invoke {@link #release} with saved state as argument, *      throwing IllegalMonitorStateException if it fails. * <li> Block until signalled or interrupted. * <li> Reacquire by invoking specialized version of *      {@link #acquire} with saved state as argument. * <li> If interrupted while blocked in step 4, throw InterruptedException. * </ol> */public final void await() throws InterruptedException {    if (Thread.interrupted())        throw new InterruptedException();    Node node = addConditionWaiter();    // 将以后线程封装成节点存入条件队列    int savedState = fullyRelease(node); // 开释曾经持有的锁(就是在调用 Condition#await 之前持有的 Lock#lock 锁),并返回开释前的锁状态    int interruptMode = 0;    while (!isOnSyncQueue(node)) {       // 查看节点是否在同步队列上        LockSupport.park(this);          // 节点还在条件队列中,则阻塞           // 节点从阻塞中被唤醒(condition#signal,Thread#interrupt),查看中断状态,设置中断解决模式        // 补充:被 condition#signal 唤醒后的线程会从条件队列转移到同步队列(先出队再入队)        // 补充:若在条件队列中就产生了中断,也会被转移到同步队列(不出队,只入队,见 checkInterruptWhileWaiting -> transferAfterCancelledWait)        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)              break;                                                        }                                                                     if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // 在同步队列期待获取资源直到胜利,判断设置中断解决模式        interruptMode = REINTERRUPT;    if (node.nextWaiter != null)  // clean up if cancelled         // nextWaiter不为空,阐明以后节点是由 Thread#interrupt 唤醒的(condition#signal 唤醒阻塞节点会设置nextWaiter为空)        // 此时以后节点同时存在于同步队列、条件队列上!然而 waitStatus 不是 CONDITION        // 须要革除条件队列中已勾销的节点        unlinkCancelledWaiters();    if (interruptMode != 0)        reportInterruptAfterWait(interruptMode); // 解决中断:抛异样,或者补上中断状态}

留神:

  1. 线程被唤醒,可能是执行了 Condition#signal(其中执行 LockSupport#unpark 来唤醒条件队列的头节点),也可能是调用了 Thread#interrupt (会更新线程的中断标识)。
  2. 如果是由 Condition#signal 唤醒的,则以后节点被唤醒后,曾经位于同步队列。
  3. 如果是由 Thread#interrupt 唤醒的,则以后节点被唤醒后,须要判断是位于同步队列还是条件队列。
    3.1 如果是位于同步队列,阐明是先失去 Condition#signal 告诉,再被 Thread#interrupt 中断。
    3.2 如果是位于条件队列,阐明未失去 Condition#signal 告诉就被 Thread#interrupt 中断了,须要自行退出到同步队列中,再从条件队列中移除。
  4. 以后节点从条件队列转移到同步队列的过程中,产生了中断,该节点依旧会在同步队列中自旋、阻塞直到获取锁,再响应中断(抛异样或从新中断)。

3.1.1 addConditionWaiter

将以后线程封装为节点(waitStatus 为 CONDITION),增加到条件队列尾部。
若条件队列不存在则进行初始化,把以后节点作为头节点(不应用 dummy node)。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#addConditionWaiter

/** * Adds a new waiter to wait queue. * @return its new wait node */private Node addConditionWaiter() {    Node t = lastWaiter;    // If lastWaiter is cancelled, clean out. // 清理条件队列中已勾销的尾节点    if (t != null && t.waitStatus != Node.CONDITION) {        unlinkCancelledWaiters();        t = lastWaiter;    }    Node node = new Node(Thread.currentThread(), Node.CONDITION); // 构建节点,尾插法    if (t == null)        firstWaiter = node;    else        t.nextWaiter = node;    lastWaiter = node;    return node;}

3.1.2 fullyRelease

开释以后线程已持有的锁/资源,返回开释之前的锁/资源。
若未持有锁,报错。

这里存在 BUG:报错之前,以后线程曾经退出到条件队列之中了,会导致条件队列存储有效的节点数据。
应该将是否持有锁的校验提前到 addConditionWaiter 之前,JDK 11 中已修复该问题。

java.util.concurrent.locks.AbstractQueuedSynchronizer#fullyRelease

final int fullyRelease(Node node) { // 开释以后线程已持有的锁    boolean failed = true;    try {        int savedState = getState(); // 获取 volatile 的 state,独占模式下示意以后线程锁持有的全副锁        if (release(savedState)) {   // 开释全副的锁            failed = false;            return savedState;        } else {            throw new IllegalMonitorStateException(); // 未持有锁,报错        }    } finally {        if (failed)            node.waitStatus = Node.CANCELLED;    }}

3.1.3 isOnSyncQueue

判断节点是否在同步队列上。

java.util.concurrent.locks.AbstractQueuedSynchronizer#isOnSyncQueue

/** * Returns true if a node, always one that was initially placed on * a condition queue, is now waiting to reacquire on sync queue. * @param node the node * @return true if is reacquiring */final boolean isOnSyncQueue(Node node) {    if (node.waitStatus == Node.CONDITION || node.prev == null)        return false;    if (node.next != null) // If has successor, it must be on queue        return true;    return findNodeFromTail(node); // 从尾节点向前遍历查找}/** * Returns true if node is on sync queue by searching backwards from tail. * Called only when needed by isOnSyncQueue. * @return true if present */private boolean findNodeFromTail(Node node) {    Node t = tail;    for (;;) {        if (t == node)            return true;        if (t == null)            return false;        t = t.prev;    }}

1. 如果 waitStatus == CONDITION 阐明肯定是位于条件队列上。

从条件队列入队,结构节点的时候默认就为 CONDITION 状态。
将节点从条件队列转移到同步队列,首先会 CAS 设置 waitStatus 状态为 CONDITION,再执行入队操作。

2. node.prev == null 阐明肯定是位于条件队列上。

同步队列只有头节点合乎 node.prev == null,然而同步队列的头节点是 dummy node,其 thread 为空。
也就是说,来调用 isOnSyncQueue 办法且合乎 node.prev == null 条件的节点,只可能是位于条件队列上的节点。

3. 如果 node.next != null 阐明肯定是处于同步队列上。

节点退出同步队列是个复合操作,最初一步是设置 node.next,当 node.next != null 阐明入队操作已执行实现。

4. 如果以上都无奈判断节点是否位于同步队列,则遍历链表查找节点。

存在 node.prev != null 然而节点还没有齐全入队胜利的状况,因为入队操作设置 prev -> tail -> next 是非原子操作。
所以须要从 tail 向前遍历,能力精确判断 node 是否位于同步队列上。
调用 findNodeFromTail 办法前,节点个别位于尾节点左近,不会遍历过多节点。

3.1.4 checkInterruptWhileWaiting

阻塞在 Condition#await 的线程被唤醒之后,调用 checkInterruptWhileWaiting 来查看是否是由线程中断唤醒的。

如果是由线程中断唤醒的,须要进一步判断如何解决中断:

  1. THROW_IE:throw new InterruptedException();
  2. REINTERRUPT:Thread.currentThread().interrupt();

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#checkInterruptWhileWaiting

/** * Checks for interrupt, returning THROW_IE if interrupted * before signalled, REINTERRUPT if after signalled, or * 0 if not interrupted. */private int checkInterruptWhileWaiting(Node node) {    // 校验以后线程是否被中断,并革除线程的中断状态    return Thread.interrupted() ?         (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :         0; // 如果线程未被中断,返回0}

3.1.5 transferAfterCancelledWait

如果阻塞在 Condition#await 的线程是被中断唤醒的,执行 transferAfterCancelledWait 判断产生中断产生时节点所在的地位。
如果是位于条件队列,则将其增加到同步队列,返回 true;否则返回 false。

如何判断中断产生时节点所在的地位?

  1. 已知 Condition#signal 办法会批改状态(CONDITION -> 0),并操作节点从条件队列出队,从同步队列入队。
  2. 如果 Condition#await 执行 CAS 批改状态胜利(CONDITION -> 0),阐明线程中断产生时 Condition#signal 还没执行,此时节点是位于条件队列,须要将节点退出同步队列。
  3. 如果 Condition#await 执行 CAS 批改状态失败(CONDITION -> 0),阐明线程中断产生时 Condition#signal 曾经执行,以后线程须要自旋期待 Condition#signal 执行完。

java.util.concurrent.locks.AbstractQueuedSynchronizer#transferAfterCancelledWait

/** * Transfers node, if necessary, to sync queue after a cancelled wait. * Returns true if thread was cancelled before being signalled. * * @param node the node * @return true if cancelled before the node was signalled */final boolean transferAfterCancelledWait(Node node) {    if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { // 通过 CAS 胜利与否来判断节点地位        enq(node); // 如果CAS胜利,阐明节点是位于条件队列,须要将它增加到同步队列        return true;    }    /*     * If we lost out to a signal(), then we can't proceed     * until it finishes its enq().  Cancelling during an     * incomplete transfer is both rare and transient, so just     * spin.     */                          // 条件队列上的节点失去告诉(Condition#signal)之后,会增加到同步队列中去。    while (!isOnSyncQueue(node)) // 这里循环检测,直到确认节点曾经胜利增加到同步队列中。        Thread.yield();    return false;}

3.1.6 unlinkCancelledWaiters

在 Condition#await 办法中,当线程从阻塞中被线程中断唤醒后,判断节点是位于条件队列中,除了将节点退出同步队列之外,还须要将节点从条件队列中移除。

官网的阐明:

  1. 持有锁时才可调用该办法。
  2. 以后线程在 Condition#wait 中阻塞,在被 Condition#signal 唤醒之前,由线程中断或期待超时唤醒。此时须要调用该办法革除条件队列中的有效节点。
  3. 只管该办法会遍历整个队列,然而只有在 Condition#signal 没有执行之前产生中断或勾销才会调用。
  4. 该办法会遍历整个条件队列,一次性把所有有效节点都革除掉,当队列中短时间呈现大量有效节点时(cancellation storms)可防止屡次遍历队列。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#unlinkCancelledWaiters

/** * Unlinks cancelled waiter nodes from condition queue. * Called only while holding lock. This is called when * cancellation occurred during condition wait, and upon * insertion of a new waiter when lastWaiter is seen to have * been cancelled. This method is needed to avoid garbage * retention in the absence of signals. So even though it may * require a full traversal, it comes into play only when * timeouts or cancellations occur in the absence of * signals. It traverses all nodes rather than stopping at a * particular target to unlink all pointers to garbage nodes * without requiring many re-traversals during cancellation * storms. */ private void unlinkCancelledWaiters() { // 革除条件队列中状态不为CONDITION的节点    Node t = firstWaiter; // 游标节点,记录以后遍历的节点    Node trail = null;    // 游标节点,记录遍历过的最初一个无效节点(状态为CONDITION)    while (t != null) {   // 从条件队列的头节点开始遍历(上面正文用next代表下一个节点)        Node next = t.nextWaiter;        if (t.waitStatus != Node.CONDITION) { // 以后t为有效节点            t.nextWaiter = null;            if (trail == null)           // 首次遍历到t为无效节点时,才会初始化trail                firstWaiter = next;      // 设置t.next为新的头节点(下一次循环校验t.next:若t.next有效,则把t.next.next设为新的头节点)            else                trail.nextWaiter = next; // 设置trail.next为t.next(把t出队,下一次循环校验t.next:若t.next有效,则把t.next.next设为trail.next)            if (next == null)                lastWaiter = trail;      // 设置trail为新的尾节点        }        else      // 以后t为无效节点            trail = t;        t = next; // 持续遍历t.next    }}

3.1.7 reportInterruptAfterWait

Condition#await 执行到最初,从阻塞中被唤醒且从新获得锁,判断 interruptMode != 0,即 Condition#await 整个过程中产生过中断,须要对中断进行对立解决。

具体见设置 interruptMode 的代码:checkInterruptWhileWaiting

  1. 如果在失去告诉之前被中断(在条件队列中),返回 THROW_IE
  2. 如果在失去告诉之后被中断(在同步队列中),返回 REINTERRUPT

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#reportInterruptAfterWait

/** * Throws InterruptedException, reinterrupts current thread, or * does nothing, depending on mode. */private void reportInterruptAfterWait(int interruptMode)    throws InterruptedException {    if (interruptMode == THROW_IE)        throw new InterruptedException();    else if (interruptMode == REINTERRUPT)        selfInterrupt();}

java.util.concurrent.locks.AbstractQueuedSynchronizer#selfInterrupt

/** * Convenience method to interrupt current thread. */static void selfInterrupt() {    Thread.currentThread().interrupt();}

3.2 Condition#awaitNanos

在 Condition 条件上阻塞,具备超时工夫。

  1. Condition#await:Block until signalled or interrupted.
  2. Condition#awaitNanos:Block until signalled, interrupted, or timed out.

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#awaitNanos

/** * Implements timed condition wait. * <ol> * <li> If current thread is interrupted, throw InterruptedException. * <li> Save lock state returned by {@link #getState}. * <li> Invoke {@link #release} with saved state as argument, *      throwing IllegalMonitorStateException if it fails. * <li> Block until signalled, interrupted, or timed out. * <li> Reacquire by invoking specialized version of *      {@link #acquire} with saved state as argument. * <li> If interrupted while blocked in step 4, throw InterruptedException. * </ol> */public final long awaitNanos(long nanosTimeout)        throws InterruptedException {    if (Thread.interrupted())        throw new InterruptedException();    Node node = addConditionWaiter();    int savedState = fullyRelease(node);    final long deadline = System.nanoTime() + nanosTimeout; // 期待截止的工夫戳    int interruptMode = 0;    while (!isOnSyncQueue(node)) {        if (nanosTimeout <= 0L) { // 已超时,查看节点所在位置,判断是否把节点退出同步队列            transferAfterCancelledWait(node);            break;        }        if (nanosTimeout >= spinForTimeoutThreshold) // 大于工夫阈值,进行阻塞;小于工夫阈值,进行自旋            LockSupport.parkNanos(this, nanosTimeout);        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) // 从阻塞中唤醒后,查看是否产生中断,如有中断则完结自旋            break;        nanosTimeout = deadline - System.nanoTime(); // 残余等待时间    }    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)        interruptMode = REINTERRUPT;    if (node.nextWaiter != null)        unlinkCancelledWaiters();    if (interruptMode != 0)        reportInterruptAfterWait(interruptMode);    return deadline - System.nanoTime(); // 返回残余的阻塞工夫}

java.util.concurrent.locks.AbstractQueuedSynchronizer#spinForTimeoutThreshold

/** * The number of nanoseconds for which it is faster to spin * rather than to use timed park. A rough estimate suffices * to improve responsiveness with very short timeouts. */static final long spinForTimeoutThreshold = 1000L;

3.3 Condition#awaitUninterruptibly

在 Condition 条件上阻塞,只能被 Condition#signal 唤醒。

  1. Condition#await:Block until signalled or interrupted.
  2. Condition#awaitNanos:Block until signalled, interrupted, or timed out.
  3. Condition#awaitUninterruptibly:Block until signalled.

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#awaitUninterruptibly

/** * Implements uninterruptible condition wait. * <ol> * <li> Save lock state returned by {@link #getState}. * <li> Invoke {@link #release} with saved state as argument, *      throwing IllegalMonitorStateException if it fails. * <li> Block until signalled. * <li> Reacquire by invoking specialized version of *      {@link #acquire} with saved state as argument. * </ol> */public final void awaitUninterruptibly() {    Node node = addConditionWaiter();    int savedState = fullyRelease(node);    boolean interrupted = false;    while (!isOnSyncQueue(node)) {        LockSupport.park(this);        if (Thread.interrupted())            interrupted = true;    }    if (acquireQueued(node, savedState) || interrupted)        selfInterrupt();}

4. Condition 告诉办法

4.1 Condition#signal

唤醒在 Condition#await 上期待最久的线程。
把条件队列的头节点出队,把它退出同步队列,并唤醒节点中的线程。
被唤醒的线程从 Condition#await 中醒来后,执行 AbstractQueuedSynchronizer#acquireQueued 期待再次获取锁。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#signal

/** * Moves the longest-waiting thread, if one exists, from the * wait queue for this condition to the wait queue for the * owning lock. * * @throws IllegalMonitorStateException if {@link #isHeldExclusively} *         returns {@code false} */public final void signal() {    if (!isHeldExclusively()) // 未持有独占锁,报错        throw new IllegalMonitorStateException();    Node first = firstWaiter;    if (first != null)        doSignal(first); // 唤醒队首节点(等待时间最长)}

4.1.1 doSignal

  1. 找到适合的可唤醒的节点,个别是条件队列的头节点,将它从条件队列出队。
  2. 如果头节点是有效节点,则出队直到找到无效节点。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#doSignal

/** * Removes and transfers nodes until hit non-cancelled one or * null. Split out from signal in part to encourage compilers * to inline the case of no waiters. * @param first (non-null) the first node on condition queue */private void doSignal(Node first) { // 把条件队列的头节点转移到同步队列    do {        if ( (firstWaiter = first.nextWaiter) == null) // 以后节点的后继节点作为新的头节点(出队),若为空,阐明队列为空            lastWaiter = null;        first.nextWaiter = null;    } while (!transferForSignal(first) &&    // 把以后节点转移到同步队列(入队),并唤醒节点上的线程(阐明条件队列的头节点不是dummy node)             (first = firstWaiter) != null); // 转移失败,取最新的firstWaiter,若不为空则重试,若为空,阐明队列为空}

4.1.2 transferForSignal

  1. 批改节点状态:CONDITION -> 0
  2. 退出到同步队列
  3. 唤醒节点

java.util.concurrent.locks.AbstractQueuedSynchronizer#transferForSignal

/** * Transfers a node from a condition queue onto sync queue. // 将一个节点从条件队列转移到同步队列 * Returns true if successful. * @param node the node * @return true if successfully transferred (else the node was * cancelled before signal) */final boolean transferForSignal(Node node) {    /*     * If cannot change waitStatus, the node has been cancelled. // 条件队列上的节点状态不为CONDITION,阐明是已勾销     */    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))        return false;    /*     * Splice onto queue and try to set waitStatus of predecessor to     * indicate that thread is (probably) waiting. If cancelled or     * attempt to set waitStatus fails, wake up to resync (in which     * case the waitStatus can be transiently and harmlessly wrong).     */    Node p = enq(node); // 增加到同步队列,返回上一个节点    int ws = p.waitStatus;    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))        LockSupport.unpark(node.thread); // 查看上一个节点,发现不具备唤醒以后节点条件,则立刻唤醒以后节点    return true;                         // 补充:node.thread 从 Condition#await 之中被唤醒,后续执行 acquireQueued 尝试获取锁}

4.2 Condition#signalAll

遍历条件队列,顺次唤醒所有节点。
所有节点都会迁徙到同步队列期待获取锁。

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#signalAll

/** * Moves all threads from the wait queue for this condition to * the wait queue for the owning lock. * * @throws IllegalMonitorStateException if {@link #isHeldExclusively} *         returns {@code false} */public final void signalAll() {    if (!isHeldExclusively())        throw new IllegalMonitorStateException();    Node first = firstWaiter;    if (first != null)        doSignalAll(first);}

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#doSignalAll

/** * Removes and transfers all nodes. * @param first (non-null) the first node on condition queue */private void doSignalAll(Node first) {    lastWaiter = firstWaiter = null;    do {        Node next = first.nextWaiter;        first.nextWaiter = null;        transferForSignal(first);        first = next;    } while (first != null);}

相干浏览:
浏览 JDK 8 源码:AQS 中的独占模式
浏览 JDK 8 源码:AQS 中的共享模式
浏览 JDK 8 源码:AQS 对 Condition 的实现

作者:Sumkor