Java: notify() vs. notifyAll() all over again

Viewed 229060

If one Googles for "difference between notify() and notifyAll()" then a lot of explanations will pop up (leaving apart the javadoc paragraphs). It all boils down to the number of waiting threads being waken up: one in notify() and all in notifyAll().

However (if I do understand the difference between these methods right), only one thread is always selected for further monitor acquisition; in the first case the one selected by the VM, in the second case the one selected by the system thread scheduler. The exact selection procedures for both of them (in the general case) are not known to the programmer.

What's the useful difference between notify() and notifyAll() then? Am I missing something?

26 Answers

However (if I do understand the difference between these methods right), only one thread is always selected for further monitor acquisition.

That is not correct. o.notifyAll() wakes all of the threads that are blocked in o.wait() calls. The threads are only allowed to return from o.wait() one-by-one, but they each will get their turn.


Simply put, it depends on why your threads are waiting to be notified. Do you want to tell one of the waiting threads that something happened, or do you want to tell all of them at the same time?

In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.

Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.


In many cases, the code to await a condition will be written as a loop:

synchronized(o) {
    while (! IsConditionTrue()) {
        o.wait();
    }
    DoSomethingThatOnlyMakesSenseWhenConditionIsTrue_and_MaybeMakeConditionFalseAgain();
}

That way, if an o.notifyAll() call wakes more than one waiting thread, and the first one to return from the o.wait() makes leaves the condition in the false state, then the other threads that were awakened will go back to waiting.

Useful differences:

  • Use notify() if all your waiting threads are interchangeable (the order they wake up doesn't matter), or if you only ever have one waiting thread. A common example is a thread pool used to execute jobs from a queue--when a job is added, one of threads is notified to wake up, execute the next job and go back to sleep.

  • Use notifyAll() for other cases where the waiting threads may have different purposes and should be able to run concurrently. An example is a maintenance operation on a shared resource, where multiple threads are waiting for the operation to complete before accessing the resource.

I think it depends on how resources are produced and consumed. If 5 work objects are available at once and you have 5 consumer objects, it would make sense to wake up all threads using notifyAll() so each one can process 1 work object.

If you have just one work object available, what is the point in waking up all consumer objects to race for that one object? The first one checking for available work will get it and all other threads will check and find they have nothing to do.

I found a great explanation here. In short:

The notify() method is generally used for resource pools, where there are an arbitrary number of "consumers" or "workers" that take resources, but when a resource is added to the pool, only one of the waiting consumers or workers can deal with it. The notifyAll() method is actually used in most other cases. Strictly, it is required to notify waiters of a condition that could allow multiple waiters to proceed. But this is often difficult to know. So as a general rule, if you have no particular logic for using notify(), then you should probably use notifyAll(), because it is often difficult to know exactly what threads will be waiting on a particular object and why.

Note that with concurrency utilities you also have the choice between signal() and signalAll() as these methods are called there. So the question remains valid even with java.util.concurrent.

Doug Lea brings up an interesting point in his famous book: if a notify() and Thread.interrupt() happen at the same time, the notify might actually get lost. If this can happen and has dramatic implications notifyAll() is a safer choice even though you pay the price of overhead (waking too many threads most of the time).

From Joshua Bloch, the Java Guru himself in Effective Java 2nd edition:

"Item 69: Prefer concurrency utilities to wait and notify".

notify() will wake up one thread while notifyAll() will wake up all. As far as I know there is no middle ground. But if you are not sure what notify() will do to your threads, use notifyAll(). Works like a charm everytime.

All the above answers are correct, as far as I can tell, so I'm going to tell you something else. For production code you really should use the classes in java.util.concurrent. There is very little they cannot do for you, in the area of concurrency in java.

Taken from blog on Effective Java:

The notifyAll method should generally be used in preference to notify. 

If notify is used, great care must be taken to ensure liveness.

So, what i understand is (from aforementioned blog, comment by "Yann TM" on accepted answer and Java docs):

  • notify() : JVM awakens one of the waiting threads on this object. Thread selection is made arbitrarily without fairness. So same thread can be awakened again and again. So system's state changes but no real progress is made. Thus creating a livelock.
  • notifyAll() : JVM awakens all threads and then all threads race for the lock on this object. Now, CPU scheduler selects a thread which acquires lock on this object. This selection process would be much better than selection by JVM. Thus, ensuring liveness.

Take a look at the code posted by @xagyg.

Suppose two different threads are waiting for two different conditions:
The first thread is waiting for buf.size() != MAX_SIZE, and the second thread is waiting for buf.size() != 0.

Suppose at some point buf.size() is not equal to 0. JVM calls notify() instead of notifyAll(), and the first thread is notified (not the second one).

The first thread is woken up, checks for buf.size() which might return MAX_SIZE, and goes back to waiting. The second thread is not woken up, continues to wait and does not call get().

Waiting queue and blocked queue

You can assume there are two kinds of queues associated with each lock object. One is blocked queue containing thread waiting for the monitor lock, other is waiting queue containing thread waiting to be notified. (Thread will be put into waiting queue when they call Object.wait).

Each time the lock is available, the scheduler choose one thread from blocked queue to execute.

When notify is called, there will only be one thread in waiting queue are put into blocked queue to contend for the lock, while notifyAll will put all thread in waiting queue into blocked queue.

Now can you see the difference?
Although in both case there will only be one thread get executed, but with notifyAll, other threads still get a change to be executed(Because they are in the blocked queue) even if they failed to contend the lock.

some guidline

I basically recommend use notifyAll all the time althrough there may be a little performance penalty.
And use notify only if :

  1. Any waked thread can make the programe proceed.
  2. performance is important.

For example:
@xagyg 's answer gives a example which notify will cause deadlock. In his example, both producer and consumer are related with the same lock object. So when a producer calls notify, either a producer or a consumer can be notified. But if a producer is woken up it can not make the programe proceed because the buffer is already full.So a deadlock happens.
There are two ways to solve it :

  1. use notifyALl as @xagyg suggests.
  2. Make procuder and consumer related with different lock object and procuder can only wake up consumer, consumer can only wake up producer. In that case, no matter which consumer is waked, it can consumer the buffer and make the programe proceed.

Waking up all does not make much significance here. wait notify and notifyall, all these are put after owning the object's monitor. If a thread is in the waiting stage and notify is called, this thread will take up the lock and no other thread at that point can take up that lock. So concurrent access can not take place at all. As far as i know any call to wait notify and notifyall can be made only after taking the lock on the object. Correct me if i am wrong.

Related