首先,我知道以前似乎已经问过这个问题了,但确实没有得到任何好的答案,所以我会再问清楚。
如果当前没有其他线程正在等待时发生通知,则此代码可能会导致死锁
while (!checkPreConditions()){
synchronized(lock){ lock.wait(); }
}
doWork();
synchronized(lock) { lock.notifyAll(); }
我试过把一个计数器用于通知的线程数,而没有线程在等待,但是这个解决方案非常麻烦。 另一个想法是暂停等待,但程序可能会无缘无故地等待 这个问题有一个共同的解决方案/模式吗?
答案 0 :(得分:2)
我认为您正在尝试使用过于简单的工具(synchronized
)来解决稍微复杂的问题。您应该阅读更高级别的并发实用程序类,如java并发包所提供的那样。
最有可能的是,semaphore将为您完成工作,因为使用信号量,获取和释放锁定机制的顺序无关紧要。即有了信号量,你可以在获得之前释放。
答案 1 :(得分:0)
如果我正确地理解了问题,我认为你在谈论'虚假的唤醒'情景。 最好的解决方案在“Object.java”javadoc本身中给出:)
以下是java doc的片段:
* A thread can also wake up without being notified, interrupted, or
* timing out, a so-called <i>spurious wakeup</i>. While this will rarely
* occur in practice, applications must guard against it by testing for
* the condition that should have caused the thread to be awakened, and
* continuing to wait if the condition is not satisfied. In other words,
* waits should always occur in loops, like this one:
* <pre>
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait(timeout);
* ... // Perform action appropriate to condition
* }
* </pre>
希望这会有所帮助。有关详细信息,请参阅此内容。
http://handling-thread.blogspot.co.uk/2012/11/what-is-spurious-wakeup-while-wait-in.html
答案 2 :(得分:0)
你错过了这个概念。在进入等待状态之前,checkPreCondition应该在同步块内。
synchronized(lock){
while (!checkPreConditions()){
lock.wait();
}
doWork();
}
synchronized(lock) { lock.notifyAll(); }