Friday, July 7, 2023

Difference between notify and notifyAll in Java - When and How to use

notify vs notifyAll in Java
What is the difference between notify and notifyAll method is one of the tricky Java questions, which is easy to answer but once the Interviewer asks follow-up questions, you either got confused or not able to provide clear-cut and to the point answers? The main difference between notify and notifyAll is that the notify method will only notify one Thread and the notifyAll method will notify all Threads which are waiting on that monitor or lock. By the way, this is something you have been reading all over places and to be frank,  this statement despite being correct is not complete, and it's very difficult to understand the difference between notify vs notifyAll by just reading this statement.

A lot of questions comes to mind like
  • Which thread will be notified if I use notify()?
  • How do I know how many threads are waiting, so that I can use notifyAll()?
  • How to call notify()?
  • What are these thread waiting for being notified etc?

Actually, the discussion of notify and notifyAll is incomplete without discussing the wait method in Java and I had touched based on this in my earlier article why to wait and notify must be called from a synchronized context. 

In order to get an answer to those questions and understand the difference between notify and notifyAll, we will use a simple Java Thread example using wait and notify code in this article. 




Difference between notify and notifyAll in Java

Java provides two methods notify and notifyAll for waking up threads waiting on some condition and you can use any of them but there is a subtle difference between notify and notifyAll in Java which makes it one of the popular multi-threading interview questions in Java. 

When you call notify only one of waiting for the thread will be woken and it's not guaranteed which thread will be woken, it depends on upon Thread scheduler. 

While if you call the notifyAll method, all threads waiting on that lock will be woken up, but again all woken thread will fight for the lock before executing the remaining code and that's why the wait is called on loop because if multiple threads are woken up, the thread which will get lock will first execute and it may reset waiting for condition, which will force subsequent threads to wait

So the key difference between notify and notifyAll is that notify() will cause only one thread to wake up while the notifyAll method will make all thread to wake up. 

These two methods are also a key part of the producer-consumer design pattern, one of the most useful multithreading patterns for Java developers. 

notify vs notifyAll in Java mulithreading




When to use notify and notifyAll in Java

Difference between notify and notifyAll in Java with ExampleThis is the follow-up question if you get past the earlier one Difference between notifyAll and notify in Java. If you understand notify vs notifyAll then you can answer this by applying a little common sense. You can use notify over notifyAll if all threads are waiting for the same condition and only one thread at a time can benefit from the condition becoming true. 

In this case, notify is optimized call over notifyAll because waking up all of them because we know that only one thread will benefit and all others will wait again, so calling the notifyAll method is just a waste of CPU cycles. 

Though this looks quite reasonable there is still a caveat that unintended recipient swallowing critical notification. by using notifyAll we ensure that all recipients will get notified. 

The great Josh Bloch has explained this in good detail in his book Effective Java, I highly recommend this book if you haven't read them already. Another one you can try is Concurrency Practice in Java and Java Thread, which discusses wait and notify methods in good detail.


notify vs notifyAll in Java


Example of notifying and notifyAll method in Java

I have put together an example to show how all threads get notified when we call the notifyAll method in Java and just one Thread will wake up when we call the notify method in Java. 

In this example three threads will wait if the boolean variable goes is false, remember boolean go is a volatile variable so that all threads will see its updated value. Initially, three threads WT1, WT2, WT3 will wait because the variable go is false than one thread NT1 will make go true and notify all threads by calling notifyAll method or notify just one thread by calling notify() method. 

In the case of notify() call, there is no guarantee which thread will wake up and you can see it by running this Java program multiple times. In the case of notifyAll, all threads will wake up but they will compete for monitor or lock and the Thread which will get the lock first will finish its execution and resetting go to false which will force the other two threads to still waiting. 

At the end of this program, you will have two threads waiting and two threads including the notification thread finished. 

The program will not terminate because the other two threads are still waiting and they are not daemon threads. The purpose of this notify and notifyAll example is to show you How to use them and How to notify and notifyAll method works in Java.



Code Example of notifying and notifyAll

Here is a complete code example of How to use the notify and notifyAll method in Java. We have already explained when to use the notify vs notifyAll method and this example will clarify the effect of calling the notify and notifyAll method in Java.

I strongly recommend to run this Java program and understand the output produced by it and try to understand it. The theory should complement practical examples and if you see any inconsistency then let us know or try to rectify it. 

Along with deadlockrace condition, and thread-safety,  inter-thread communication is one of the fundamentals of concurrent programming in Java.

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Java program to demonstrate How to use notify and notifyAll method in Java and
 * How to notify and notifyAll method notifies thread, which thread gets woke up etc.
 */

public class NotificationTest {

    private volatile boolean go = false;

    public static void main(String args[]) throws InterruptedException {
        final NotificationTest test = new NotificationTest();
     
        Runnable waitTask = new Runnable(){
     
            @Override
            public void run(){
                try {
                    test.shouldGo();
                } catch (InterruptedException ex) {
                    Logger.getLogger(NotificationTest.class.getName()).
                           log(Level.SEVERE, null, ex);
                }
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
     
        Runnable notifyTask = new Runnable(){
     
            @Override
            public void run(){
                test.go();
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
     
        Thread t1 = new Thread(waitTask, "WT1"); //will wait
        Thread t2 = new Thread(waitTask, "WT2"); //will wait
        Thread t3 = new Thread(waitTask, "WT3"); //will wait
        Thread t4 = new Thread(notifyTask,"NT1"); //will notify
     
        //starting all waiting thread
        t1.start();
        t2.start();
        t3.start();
     
        //pause to ensure all waiting thread started successfully
        Thread.sleep(200);
     
        //starting notifying thread
        t4.start();
     
    }
    /*
     * wait and notify can only be called from synchronized method or bock
     */

    private synchronized void shouldGo() throws InterruptedException {
        while(go != true){
            System.out.println(Thread.currentThread()
                         + " is going to wait on this object");
            wait(); //release lock and reacquires on wakeup
            System.out.println(Thread.currentThread() + " is woken up");
        }
        go = false; //resetting condition
    }
 
    /*
     * both shouldGo() and go() are locked on the current object referenced by "this" keyword
     */

    private synchronized void go() {
        while (go == false){
            System.out.println(Thread.currentThread()
            + " is going to notify all or one thread waiting on this object");

            go = true; //making condition true for waiting thread
            //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
            notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
        }
     
    }
 
}

Output in case of using notify
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT1,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT1,5,main] finished Execution

Output in case of calling notifyAll
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT2,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT3,5,main] is woken up
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] finished Execution
Thread[WT1,5,main] is woken up
Thread[WT1,5,main] is going to wait on this object



You can see how you can interact with threads using notify() and notifyAll() methods. I




Summary

In short here are answers to questions on notify and notifyAll we have raised at the start of this tutorial:

Which thread will be notified if I use notify()?

No guaranteed,  ThreadScheduler will pick a random thread from a pool of waiting for a thread on that monitor. What is guaranteed is that only one Thread will be notified.

How do I know how many threads are waiting, so that I can use notifyAll()?

It depends upon your application logic while coding you need to think whether a piece of code can be run by multiple threads or not. A good example to understand inter-thread communication is implementing the producer-consumer pattern in Java.

How to call notify()?

Wait() and notify() method can only be called from synchronized method or block, you need to call notify method on an object on which other threads are waiting.

What are these thread waiting for being notified etc?

Thread wait on some condition e.g. in the producer-consumer problem, producer thread wait if the shared queue is full and consumer thread wait if the shared queue is empty. Since multiple threads are working with a shared resource they communicate with each other using the wait and notify method.

That’s all on What is the difference between the notify and notifyAll method in Java and when to use notify vs notifyAll in Java. Now you should be able to understand and use the notify and notifyAll method for inter-thread communication in your Java program.


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

5 comments:

  1. Good article for those who write low level Java framework code.
    Exactly because it is so easy to confuse things and introduce bugs, it is recommended for any application level code to use higher level frameworks such as the java util concurrent package http://www.ibm.com/developerworks/java/library/j-5things4/index.html or frameworks like akka.io.

    ReplyDelete
  2. I understand real difference between notify and notifyAll by seeing its effect while implementing ReadWriteLock. in ReadWriteLock, when writer finished writing, it has to notify all reader and other writers which are waiting for lock. Now if it used just notify in place of notifyAll then it might happen that a reader woke up and goes to sleep without doing anything because another writer is waiting. If we call notifyAll, then all will woke up and get a chance to proceed. Similarly if only readers are waiting then a cal to notifyAll will woke all thread at once instead of working them one by one by us ing notify me thod.

    ReplyDelete
  3. One more thing..these methods can't be overridden. These are defined as final methods. For more interview questions, please visit:
    http://ankitagarwaljava.blogspot.in/

    ReplyDelete
  4. One of the main reason, why you will use notifyAll over notify is number of conditions, which can cause a thread to wait. If your thread can wait due to multiple conditions, then you must call notifyAll() method, as you don't have ability to notify threads for specific conditions. This limitation is sorted out by ReentrantLock and Condition, ReentrantLock.newCondition() provides ability to notify threads, which are waiting for a specific condition using signal() and signalAll() method. Anyway, Using notifyAll() instead of notify() is less desirable due to the thrashing effect it has of waking up all the threads to compete for a lock when can do the job

    ReplyDelete
  5. Thank you so much. Sample program is really good.

    ReplyDelete