2013-12-14 35 views
2

在这本书我读它说:需要由于原本 设置和发送通知和测试 得到通知之间存在的竞争条件为什么必须等待并通知从同步块/方法中调用?

这种技术。如果wait()和notify()机制在保持同步锁定时未调用 ,则不会保证收到通知。

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

编辑:嗯,我现在看到,这可能是一个重复的问题Why must wait() always be in synchronized block ,但它接缝的答案着眼于使条件检查,并要等待同步。从shrini1000

反例:

我还可以这样做:
while(!condition) { synchronized(this) { wait(); } }
这意味着仍然有检查的条件和等待,即使 如果等待()是在同步正确调用之间的竞争块。那么在这个限制背后还有其他什么原因,这可能是由于它在0122中执行的 ?

+0

我不认为答案是有的,在我的问题的反例的原因。 – croraf

+0

这里没有反例。您的wait()调用位于同步块中。 – EJP

+1

其根本原因是内存模型的工作方式 - 您可以查看:http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.2详细说明等待集如何工作。 – assylias

回答

0

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

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

作为反例,请考虑finally区块。 Java只强制它在try块之后,但是你是唯一一个应该知道该块应该进入哪个块的人;你甚至可以把它留空(这会错过finally的那一点)。

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(); 
    } 
} 

+0

是的,阅读了一段时间后,我认为这本书的作者意味着关于这种情况。这是“Java线程,第三版”。 O'Reilly,我不推荐。 – croraf

+0

希望我已经回答了您的问题。那么你可以通过java思考(只需阅读并行章节就足够了解线程),更多细节jcip是最好的。 – Vipin

+0

是的,你认为你回答了作者的意图,但这不完全是我的问题。无论如何,我的问题并不重要。关于jcip我有这个,我会在阅读本书后阅读它。我会给你投票,但不是这个标记,原因;) – croraf