为什么在AQS(AbstractQueuedSynchronizer)的await方法中使用”while”?

huangapple go评论72阅读模式
英文:

Why use "while" in the await method of AQS(AbstractQueuedSynchronizer)

问题

在AQS(AbstractQueuedSynchronizer)的await方法中:

我想知道在以下代码中的while的含义是什么:

while (!isOnSyncQueue(node)) {

我认为如果这个节点正常被唤醒(没有被中断),那么在另一个线程执行了signal方法之后,它肯定会被移动到同步队列,并且会在另一个线程执行解锁方法时被唤醒。

所以是否可能出现节点正常唤醒但不在同步队列中的情况呢?如果不可能的话,我认为这里应该使用if而不是while

(请注意,这是对代码中while语句的解释和提问,并非翻译。)

英文:

In the await method of AQS (AbstractQueuedSynchronizer):
I want to know the meaning of while in while (!isOnSyncQueue(node)) {

I think that if this node is woken up normally (without being interrupted), It will definitely be moved to the sync queue after the signal method is executed by another thread, and then woken up by executing the unlock method in another thread.

So there could be a situation where a node is waking up normally, but not in the sync queue? If that's not possible, I think if should be used here instead of 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);
}

答案1

得分: 3

唤醒有两种类型。一种是常规类型,另一种是虚假的类型。此代码:

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

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

英文:

Wakeups come in two flavours. The usual kind and the spurious kind. This code:

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

Keeps looping until isOnSyncQueue(node) returns false and is a while instead of an if, because the wake up might be spurious and not because the condition being waited for has occurred.

答案2

得分: 1

当 (!isOnSyncQueue(node)) {
    LockSupport.park(this);
    若 ( (interruptMode = checkInterruptWhileWaiting(node)) != 0 )
        中断;
}

这段代码的作用是在花括号 {} 中的命令,会在 isOnSyncQueue(node) 返回 false 之前不断执行。如果用 if 而不是 while,这些语句只会被执行一次。

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

What this does is execute the commands inside the pair of curly braces {}, until isOnSyncQueue(node) returns false. If it was an if instead of a while those statements would be executed only once.

答案3

得分: 0

避免由用户取消停放,但不通过信号进行,以提高鲁棒性。

英文:

Avoid unparking by the user but not by signal for robustness.

huangapple
  • 本文由 发表于 2020年8月24日 23:09:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63563728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定