使用wait和notify时避免死锁

时间:2014-02-26 11:08:29

标签: java multithreading concurrency synchronization deadlock

首先,我知道以前似乎已经问过这个问题了,但确实没有得到任何好的答案,所以我会再问清楚。

如果当前没有其他线程正在等待时发生通知,则此代码可能会导致死锁

while (!checkPreConditions()){
    synchronized(lock){ lock.wait(); }    
}
doWork();
synchronized(lock) { lock.notifyAll(); }

我试过把一个计数器用于通知的线程数,而没有线程在等待,但是这个解决方案非常麻烦。 另一个想法是暂停等待,但程序可能会无缘无故地等待 这个问题有一个共同的解决方案/模式吗?

3 个答案:

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