Reputation: 1273
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
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
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
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