Tom
Tom

Reputation: 1273

avoiding deadlock when using wait and notify

Firstly, i know that it seems like this question has been asked before, and it did but i didn't get any good answer so i will ask again more clearly.

This code may cause deadlock if the notify happens when no other thread is currently waiting

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

I'v tried putting a counter for the number of threads notifying while no threads are waiting but this solution was a bit cumbersome.. another idea was to timeout the wait but then the program may wait for no reason.
is there a common solution / pattern for that problem?

Upvotes: 0

Views: 1751

Answers (3)

Mak
Mak

Reputation: 614

You are missing the concept. checkPreCondition should be inside the sync block just before getting into wait condition.

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

   synchronized(lock) { lock.notifyAll(); }

Upvotes: 0

Mak
Mak

Reputation: 614

If I understood question correctly I think you are talking about 'spurious wakeups' scenario. And best solution is given in the "Object.java" javadoc itself :)

Below is the snippet of 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>

Hope this helps. For further details you can see this.

http://handling-thread.blogspot.co.uk/2012/11/what-is-spurious-wakeup-while-wait-in.html

Upvotes: 0

Daniel S.
Daniel S.

Reputation: 6650

I think you are trying to use a too simple tool (synchronized) to solve a problem which is slightly more complex. You should read up on higher level concurrency utility classes, as provided by the java concurrency package.

Most likely, a semaphore will do the job for you, because with semaphores, the order of acquiring and releasing the locking mechanism doesn't matter. I.e. with a semaphore, you can release before acquiring.

Upvotes: 3

Related Questions