在我正在阅读的书中说:
由于竞争条件原本需要这种技术 在设置和发送通知和测试之间存在 收到通知。如果是wait()和notify()机制 在持有同步锁时没有调用,就没有了 保证收到通知的方式。
不明白这究竟意味着什么,为什么竞争条件会发生?
编辑:嗯,我现在看到这可能是Why must wait() always be in synchronized block的重复问题 但它接着说答案集中在进行条件检查并等待同步。
来自shrini1000的反例:
我仍然可以这样做:
while(!condition) { synchronized(this) { wait(); } }
这意味着在检查状况和等待之间仍然存在竞争 如果在同步块中正确调用wait()。那是有的 这种限制背后的任何其他原因,可能是由于它的方式 用Java实现?
答案 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
)。