为什么必须等待并通知同步块/方法?

时间:2013-12-14 22:19:04

标签: java multithreading concurrency wait notify

在我正在阅读的书中说:

  

由于竞争条件原本需要这种技术   在设置和发送通知和测试之间存在   收到通知。如果是wait()和notify()机制   在持有同步锁时没有调用,就没有了   保证收到通知的方式。

不明白这究竟意味着什么,为什么竞争条件会发生?

编辑:嗯,我现在看到这可能是Why must wait() always be in synchronized block的重复问题 但它接着说答案集中在进行条件检查并等待同步。

来自shrini1000的反例:

  

我仍然可以这样做:
  while(!condition) { synchronized(this) { wait(); } }
  这意味着在检查状况和等待之间仍然存在竞争   如果在同步块中正确调用wait()。那是有的   这种限制背后的任何其他原因,可能是由于它的方式   用Java实现?

2 个答案:

答案 0 :(得分:1)

必须完全是关于作者必须在您复制的文章之前提出的技术。我不确定你正在读哪本书,但我会尝试回答这个问题。

我读了一本类似的书“Thinking in Java”,谈到了同样的竞争条件。它建议使用wait和notify来防止这种情况,这样代码就不会错过通知信号。

  

使用notify()/ wait()或notifyAll协调两个线程时(   )/ wait(),可能会错过一个信号。假设T1是一个线程   通知T2,并且使用两个线程实现   以下(有缺陷的)方法:

T1:

synchronized(sharedMonitor) {
    <setup condition for T2>
    sharedMonitor.notify();
}

T2:

while(someCondition) {
    // Assume that T2 evaluates someCondition and finds 
    // it true, now when program goes to next line thread
    // scheduler switches to T1 and executes notify again
    // after when control comes to T2 it blindly executes
    // wait(), but it has already missed notify so it will
    // always be waiting.

    .... some code ....

    synchronized(sharedMonitor) {
        sharedMonitor.wait();
    }
}

(T2的设置条件)是阻止T2调用wait()的动作(如果尚未调用)。

解决方案是防止someCondition变量上的竞争条件。这是T2的正确方法:

synchronized(sharedMonitor) {
    while(someCondition) {
        sharedMonitor.wait();
    }
}

答案 1 :(得分:0)

事情可能被滥用的事实几乎不是一个反例。

Java只强制wait()notify()是同步块的一部分(因为这是它们应该被使用的唯一方式),但是你需要定义块边界。 / p>

作为反例,请考虑finally阻止。 Java只强制它在try块之后出现,但你是唯一一个应该知道应该进入try块的人;你甚至可以把它留空(这会遗漏finally)。