首先,我知道以前似乎已经问过这个问题了,虽然确实可以,但是我没有得到很好的答案,所以我会再清楚地问一遍。
如果当前没有其他线程正在等待时发生通知,则此代码可能会导致死锁
while (!checkPreConditions()){
synchronized(lock){
lock.wait();
}
}
doWork();
synchronized(lock) {
lock.notifyAll();
}
我尝试为没有线程在等待的线程数设置一个计数器,但是此解决方案有点麻烦。另一个想法是使等待超时,但是程序可能无缘无故等待。这个问题有共同的解决方案/模式吗?
我认为您正在尝试使用过于简单的工具(synchronized
)解决稍微复杂一些的问题。您应该阅读java并发包提供的更高级别的并发实用程序类。
[很有可能,semaphore将为您完成这项工作,因为使用信号量,获取和释放锁定机制的顺序无关紧要。即带有信号灯,您可以在获取之前释放它。
如果我正确理解了问题,我认为您是在谈论“虚假唤醒”场景。最好的解决方案是在“ 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
您缺少这个概念。在进入等待状态之前,checkPreCondition应该位于同步块内。
synchronized(lock){
while (!checkPreConditions()){
lock.wait();
}
doWork();
}
synchronized(lock) { lock.notifyAll(); }