I have read that we should always called a wait()
from within a loop:
while (!condition) { obj.wait(); }
It works fine without a loop so why is that?
I have read that we should always called a wait()
from within a loop:
while (!condition) { obj.wait(); }
It works fine without a loop so why is that?
There might be more then just one worker waiting for a condition to become true.
If two or more worker get awake (notifyAll) they have to check the condition again. otherwise all workers would continue even though there might only be data for one of them.
Because wait and notify are used to implement condition variables and so you need to check whether the specific predicate you're waiting on is true before continuing.
You need not only to loop it but check your condition in the loop. Java does not guarantee that your thread will be woken up only by a notify()/notifyAll() call or the right notify()/notifyAll() call at all. Because of this property the loop-less version might work on your development environment and fail on the production environment unexpectedly.
For example, you are waiting for something:
synchronized (theObjectYouAreWaitingOn) {
while (!carryOn) {
theObjectYouAreWaitingOn.wait();
}
}
An evil thread comes along and:
theObjectYouAreWaitingOn.notifyAll();
If the evil thread does not/can not mess with the carryOn
you just continue to wait for the proper client.
Edit: Added some more samples. The wait can be interrupted. It throws InterruptedException and you might need to wrap the wait in a try-catch. Depending on your business needs, you can exit or suppress the exception and continue waiting.
It's answered in documentation for Object.wait(long milis)
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. 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:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(For more information on this topic, see Section 3.2.3 in Doug Lea's "Concurrent Programming in Java (Second Edition)" (Addison-Wesley, 2000), or Item 50 in Joshua Bloch's "Effective Java Programming Language Guide" (Addison-Wesley, 2001).