Why wait() and notify() method should be called inside a loop in Java? Example

Hello Java programmers, if you have used the wait() and notify() method in Java then you know that the standard idiom of calling the wait() method uses a loop, but have you ever thought why? This is even advised by none other than Joshua Bloch, a Java guru and author of the popular Effective Java book, a must-read for any Java programmer. When I first started using this method, I was puzzled why not just use the if block because ultimately we are testing for a condition and then either waiting or going for further processing. An if block is more readable for the testing condition than a while loop like for the classic producer-consumer problem, the waiting condition for producer thread could be written as :

if(queue.isFull()){
 
  queue.wait()
 
}
 
queue.add(item);

This says if the queue is full then wait, otherwise insert an element into the queue. This looks fine at first sight but when you think through about this in a multi-threaded scenario, you will spot the problem and that's what you will learn in this article.

 Btw, this is my second article exploring how to use the wait-notify method in Java. Earlier I have written about why wait and notify is called from the synchronized context and today you'll learn why a loop is necessary for the wait-notify block. If you haven't read that article, you may find it interesting and useful.




What is the problem using if block with wait-notify in Java?

This works fine in ideal conditions, but the programming world is not always ideal. In an ideal condition, your thread will only wake up if the consumer thread has consumed one element and now the queue is not full, but in the real world, the waiting thread can be woken up even if the condition has not changed like an evil thread sends an incorrect notification.

If you use the if block then you are not going to check the waiting condition again before start processing or adding another item in the queue. In that case, you end up putting one more element in the queue which is full, which could create an error or exception.

This is why you should always check the waiting condition in a loop instead of if block.

There is another scenario, where multiple producers are waiting for a spot in the queue. If a user called notifyAll() and informed all waiting threads about the one spot being available.

After receiving this notification, one of the threads will go for it and fill that spot but when another thread gets wake-up the spot is already filled. If you don't check the condition in the loop then you end up adding more elements in the already full queue.

When you check the waiting condition in the loop you ensure that the thread will test the condition after it wakes up to see if the condition still holds or not. If you are not familiar with notify and notifyAll method, you can further see these Java Multithreading courses to learn more.

Why wait() and notify() method should be called from loop in Java?



Reasons due to which a thread can wake up in Java

Here are a couple of reasons when a thread can incorrectly or wrong wake up in Java:

1. Misdelivered notification: 
The order in which Java threads execute after receipt of a notifyAll() signal is unspecified. This means it's possible that an unrelated thread could start executing and discover that its condition predicate is satisfied. Consequently, it could resume execution despite being required to remain dormant.


2. Spurious wakeups: 
Certain Java Virtual Machine (JVM) implementations are vulnerable to spurious wakeups that result in waiting threads waking up even without a notification

This is also true for await() method which is a new method for Condition class but similar to wait().


The wrong way to use the wait() method


synchronized (object) {
 
  if (condition does not hold) {
 
     object.wait();
 
  }
 
  // Proceed when condition holds
 
}


The right way to use the wait() method:

synchronized (object) {
 
   while (condition does not hold) {
 
     object.wait();
 
   }
 
   // Proceed when condition holds
 
}


That's all about why the wait() method should be called inside the loop in Java instead of if block. As I have said before, even the Java guru, Joshua Bloch, has written many key classes of the java.lang package has advised this in his classic Effective Java book, a must-read for any serious Java programmer. It will help you to avoid any such mistakes in your day-to-day programming task.

Other Java Multithreading and Concurrency Articles you may like
  • The Java Developer RoadMap (roadmap)
  • Difference between atomic, synchronized and volatile in Java (answer)
  • 5 Courses to Learn Java Multithreading in-depth (courses)
  • 50+ Thread Interview Questions for Beginners (questions)
  • 6 Concurrency Books Java developer can read (books)
  • What is happens before in Java Memory model? (answer)
  • Difference between Cyclic Barrier and CountDownLatch in Java? (answer)
  • Top 5 skills to Crack Coding interviews (article)
  • Top 5 Books to Master Concurrency in Java (books)
  • 10 Java Multithreading and Concurrency Best Practices (article)
  • 10 Advanced books for Experienced Programmers (books)
  • Understanding the flow of data and code in Java program (answer)
  • Is Java Concurrency in Practice still valid? (answer)
  • 10 Tips to become a better Java Developer (tips)
  • 10 Advanced Core Java Courses for Experienced Programmers (courses)

Thanks for reading this article so for. If you like the Java Thread tutorial, then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.

P. S. - If you are new to Java Multithreading and looking for a free Java multithreading course to the master thread concepts then I also suggest you check out this Java Multithreading free course on Udemy. It's completely free and all you need is a free Udemy account to join these thread related courses for Java programmers.

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.