java - 为什么 java.util.concurrent.ArrayBlockingQueue 在调用 await() 时使用 'while' 循环而不是 'if'?

标签 java multithreading concurrency

我一直在玩我自己的版本,使用“if”,一切似乎都运行良好。当然,如果使用 signalAll() 而不是 signal(),这会严重崩溃,但是如果一次只通知一个线程,这怎么会出错呢?

他们的代码 here - 查看 put() 和 take() 方法;在 JavaDoc for Condition 的顶部可以看到一个更简单、更切题的实现。 .

下面是我实现的相关部分。

public Object get() {
    lock.lock();
    try {
        if( items.size() < 1 )
            hasItems.await();
        Object poppedValue = items.getLast();
        items.removeLast();
        hasSpace.signal();
        return poppedValue; 
    } catch (InterruptedException e) {
        e.printStackTrace();
        return null;
    } finally {
        lock.unlock();
    }
}

public void put(Object item) {
    lock.lock();
    try {
        if( items.size() >= capacity )
            hasSpace.await();
        items.addFirst(item);
        hasItems.signal();
        return;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
}

附言我知道一般来说,尤其是在像这样的 lib 类中,应该让异常渗透。

最佳答案

防止虚假唤醒。 JVM 无法向您保证线程将再次开始运行的唯一可能原因是因为您以预期的方式调用了信号。有时它会不小心启动并运行(Spurious wake up)。所以如果你想要运行的条件实际上不是真的,你必须再次等待。

这在 wait 方法的 javadoc 中有解释: http://java.sun.com/javase/6/docs/api/java/lang/Object.html#wait%28long%29

并在文档中提到等待: http://java.sun.com/javase/6/docs/api/java/util/concurrent/locks/Condition.html#await%28%29

The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or

  • Some other thread invokes the signalAll() method for this Condition; or

  • Some other thread interrupts the current thread, and interruption of thread suspension is supported; or

* A "spurious wakeup" occurs.

Condition 接口(interface)的某些实现可能会抑制虚假唤醒,但依赖于此将依赖于实现细节并使您的代码不可移植。

关于java - 为什么 java.util.concurrent.ArrayBlockingQueue 在调用 await() 时使用 'while' 循环而不是 'if'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2960581/

相关文章:

java - 在 Java 中对字符串使用 >= 和 <=

java - 点击 FAB 上的 Alpha 背景

java - Hibernate @Formula 在 PUT 响应中返回旧值

java - 动态元素里面有几个 'li'

python - 使用 asyncio 创建两个并发的异步任务

multithreading - 我可以获得持有 CriticalSection 的线程的 id 吗?

linux - 与 C++ 初始值设定项有关的内存一致性

c# - 更新并发事务 C# 的数量问题

C信号量奇怪的优先行为

multithreading - 我正在做的事情可以防止死锁吗?