为什么在AQSAbstractQueuedSynchronizer的await方法中使用“ while”

问题描述

在AQS(await)的AbstractQueuedSynchronizer方法中: 我想知道while

while (!isOnSyncQueue(node)) {的含义

我认为,如果该节点正常唤醒(不被中断),则肯定会在另一个线程执行signal方法之后将其移至同步队列,然后通过在另一个线程中执行unlock方法唤醒

那么可能存在节点正常唤醒但不在同步队列中的情况?如果不可能,我认为这里应该使用if而不是while

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    Node node = addConditionWaiter();
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    while (!isOnSyncQueue(node)) {
        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);
}

解决方法

唤醒有两种口味。通常的种类和spurious种类。这段代码:

while (!isOnSyncQueue(node)) {
    ...
}

保持循环,直到isOnSyncQueue(node)返回false并且是while而不是if,因为唤醒可能是虚假的,而不是因为等待的条件已经发生了。

,
while (!isOnSyncQueue(node)) {
    LockSupport.park(this);
    if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
        break;
}

这是在一对大括号{}中执行命令,直到isOnSyncQueue(node)返回false。如果它是if而不是while,则这些语句将只执行一次。