多线程 – 条件的哪些实现不需要当前线程来保持锁定?

最近,我阅读了The Art of Multiprocessor Programming第8章中关于“监视器和阻塞同步”的一些示例,它们使用了Condition对象的signalAll(),而没有获取与该Condition相关联的锁.

令人惊讶的是,我没有在book’s errata中找到这些示例的任何修复.此外,他们建议对FifoReadWriteLock的图8.12的示例进行修正,但是他们继续使用signalAll()而不保持锁定.这扰乱了我,我试图找到关于这些示例的其他注意事项,以了解这些Java示例以这种方式编写的原因.

例如,问题“How does a read-write mutex/lock work?”的answer显示了相同的FifoReadWriteLock实现示例,它实现了writeUnlock():

void writeUnlock() {
    writer = false;
    condition.signalAll();
}

关于没有锁定获取,您可以阅读两个不同的原因:

>仅将其用作伪代码
>某些条件变量的实现不要求锁定信号.

book使用Java中的示例以来,很难接受第一个参数,并明确说:

The book uses the Java programming language.

关于第二点,我知道java.util.concurrent.locks.Condition中的Java API为signal()方法的状态:

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called.

如果仅“实施”,则意味着它不是强制性的.然而,据我所知,我发现任何不符合此要求的实施方案.所以我想知道Java Condition的哪些实现不需要当前线程来保存锁?

最佳答案
我不知道JDK中的任何Condition实现允许在不拥有监视器的情况下等待或发送信号.

几乎所有的java.util.concurrent类都依赖于AbstractQueuedSynchronizer,它与内置的监视器方法wait()/ notify()/ notifyAll()建立了相同的契约,即它提供的条件变量,即它需要拥有内部锁为了允许调用await()/ signal()/ signalAll().

如果您尝试使用建议的FifoReadWriteLock的简单示例,您会发现它的writeUnlock()方法会产生大量的IllegalMonitorStateExceptions.如果从其他方法应用lock-try-finally方法,这些异常将消失.

虽然确实拥有监视器并不是绝对需要等待或发出信号,但通常它是更好的方法,因为它可以避免您从有条件的读取中获取,它不应该像同一监视器的内部等待集之间的切换那样过于昂贵仍然可以相当有效地完成,因为大多数情况下,您需要它来进行信令和调度,而不仅仅是信令.

转载注明原文:多线程 – 条件的哪些实现不需要当前线程来保持锁定? - 代码日志