Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should wait() always be called inside a loop

I have read that we should always call a wait() from within a loop:

while (!condition) { obj.wait(); } 

It works fine without a loop so why is that?

like image 589
Geek Avatar asked Jun 24 '09 12:06

Geek


People also ask

Why must wait () always be in synchronized block?

As Michael Borgwardt points out, wait/notify is all about communication between threads, so you'll always end up with a race condition similar to the one described above. This is why the "only wait inside synchronized" rule is enforced.

What's the purpose of the object wait () method?

wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). The current thread must own this object's monitor.

What is purpose of wait () method in multithreading in Java?

The wait() method causes the current thread to wait indefinitely until another thread either invokes notify() for this object or notifyAll().

Why wait notify called from synchronized?

Calling notify() or notifyAll() methods issues a notification to a single or multiple threads that a condition has changed and once the notification thread leaves the synchronized block, all the threads which are waiting for fight for object lock on which they are waiting and lucky thread returns from wait() method ...


2 Answers

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.

like image 64
akarnokd Avatar answered Oct 21 '22 10:10

akarnokd


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).

like image 37
Tadeusz Kopec for Ukraine Avatar answered Oct 21 '22 09:10

Tadeusz Kopec for Ukraine