【问题标题】:Which implementations of Condition do not require current thread to hold the lock?Condition 的哪些实现不需要当前线程持有锁?
【发布时间】:2016-07-26 17:52:17
【问题描述】:

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

令人惊讶的是,我在book’s errata 中没有找到针对这些示例的任何修复。此外,他们建议对图 8.12 中的 FifoReadWriteLock 示例进行更正,但他们继续使用 signalAll() 而不持有锁。这让我感到不安,我试图找到有关这些示例的其他考虑因素,以了解这些 Java 示例以这种方式编写的原因。

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

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

关于没有锁获取你可以读到两个不同的原因:

  1. 仅将其用作伪代码
  2. 条件变量的某些实现不需要持有锁才能发出信号。

很难接受第一个参数,因为book 使用 Java 中的示例并明确表示:

本书使用Java编程语言。

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

当调用此方法时,实现可能(通常会)要求当前线程持有与此 Condition 关联的锁。

如果“一个实现可能”,这意味着它不是强制性的。然而,据我所知,我没有找到任何不满足此要求的实现。所以我想知道JavaCondition的哪些实现不需要当前线程来持有锁?

【问题讨论】:

  • 还要注意Condition JavaDocA Condition implementation can provide behavior and semantics that is different from that of the Object monitor methods, such as guaranteed ordering for notifications, or not requiring a lock to be held when performing notifications.中代码示例正下方的句子

标签: multithreading parallel-processing locking java.util.concurrent concurrent-programming


【解决方案1】:

我不知道 JDK 中有任何 Condition 实现允许等待或发出信号而不同时拥有监视器。

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

如果您使用建议的FifoReadWriteLock 尝试一个简单的示例,您会发现由于其writeUnlock() 方法,它会喷出大量的IllegalMonitorStateExceptions。如果您从其他方法中应用 lock-try-finally 方法,这些异常就会消失。

虽然确实拥有监视器并不是绝对需要等待或发出信号,但它通常是更可取的方法,因为它可以让您免于读取激烈的条件,它不应该太昂贵,因为内部等待集之间的切换同一个监视器仍然可以相当有效地完成,因为大多数情况下您需要它来发送信号和调度,而不仅仅是发送信号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多