0

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?

Tom
  • 1,203
  • 4
  • 21
  • 36
  • I'm not sure if I understood your question correctly. Please give additional information about the purpose for what you need this construction. Maybe this will open a broader range of thinking and allow for more ideas for solutions by the readers of this question. – Daniel S. Feb 26 '14 at 11:24
  • This: http://stackoverflow.com/a/17812574/995891 - you can not miss a `countDown()` (but works only if you need to wait once) – zapl Feb 26 '14 at 11:25
  • 1
    When you say "deadlock", do you mean that a thread hangs (e.g. stays in wait() forever, because no other thread wakes it)? I'm just asking so I can understand your question. A deadlock is defined as a situation where two threads are involved, and both threads are waiting for the other thread to release an object, but none of them ever releases it, because they both wait. If just one thread is blocked, then it's not a deadlock. – Daniel S. Feb 26 '14 at 14:28
  • Yes. At least one thread stays in wait forever. – Tom Feb 26 '14 at 15:44
  • That's still not clear. Please put a bit more effort into your question. – Daniel S. Feb 26 '14 at 15:45
  • @zapl countlatch cant count up. This scenario is more dynamic than that it requires both counting up and down – Tom Feb 26 '14 at 15:46
  • Daniel, u have seemed to understand the question. If u think a certain part needs clarification or elaboration, please specify. – Tom Feb 26 '14 at 15:48
  • Unclear for me: what are the threads involved and how do they interact (why wait/notify?). That thread interaction schema is unclear and a better solution might even be a completely different schema. A Wait/Notify schema for multiple threads sounds a bit awkward (and scenarios I could imagine might be better off using some sort of `BlockingQueue`) – zapl Feb 26 '14 at 16:36
  • @Tom you don't say what you are trying to achieve. Why not just write? synchronized(lock) { doWork(); } What does that fail to accomplish that you are trying to accomplish? – Solomon Slow Feb 27 '14 at 02:47

3 Answers3

3

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.

Daniel S.
  • 6,458
  • 4
  • 35
  • 78
  • Semaphore doesnt fit the job because the number of locks is limited and also a case of release before acquiring is possible. – Tom Feb 26 '14 at 11:44
0

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

Mak
  • 596
  • 5
  • 10
0

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(); }
Mak
  • 596
  • 5
  • 10