问题描述
在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
,则这些语句将只执行一次。