Home  Synchronization and concurrency  wait/notify  final  volatile  synchronized keyword  Java threading  Deadlock (and avoiding it)  Java 5: ConcurrentHashMap  Atomic variables  Explicit locks  Queues  Semaphores  CountDownLatch  CyclicBarrier

The notifyAll() method

An alternative to notify() is notifyAll(). As the name implies, this method wakes up all threads that are waiting on the given object. So which is appropriate where?

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. For example, imagine we have a fixed-size buffer object. Threads can add objects to the buffer, but must wait if the buffer is full. The class also has a clear() method to empty the buffer:

public class Buffer {
  private List buffer = new ArrayList();

  public void addItem(V obj) {
    synchronized (buffer) {
      while (buffer.size() >= maxSize) {
        buffer.wait();
      }
      buffer.add(obj);
    }
  }

  public void clear() {
    synchronized (buffer) {
      buffer.clear();
      buffer.notifyAll();
    }
  }
}

Now, it's crucial that the clear() method calls notifyAll() because it can't tell how many threads are waiting on the buffer, and it performs an action that can potentially allow various of those threads to proceed.

Generally, if you accidentally call notifyAll() where only notify() is necessary, this should not cause your program logic to fail: at worst it will cause some unnecessary context switches as a bunch of threads are in turn woken up, only to find that the condition they were waiting for has not yet been met, and that they must immediately wait again. But the converse is not true, as in the Buffer.clear() method above: here, notifyAll() is necessary because there could be several threads waiting, and clear() is the only method that does something to allow them to proceed.

Of course, the semantics of the synchronized lock still apply with notifyAll(). That is to say, each of the awoken threads will, in turn, acquire the lock and proceed. The next awoken thread 'in the queue' will proceed only after the previous one has released the lock, either by exiting the synchronized block or by re-entering the wait() method.

Article written by Neil Coffey (@BitterCoffey).

Software

 LetterMeister (word puzzle game for iPhone)
 Currency Quoter (currency converter/predictor)
 French Vocab Games for iPhone/iPad
 Vocabularium: create Spanish vocab podcasts


Java programming articles and tutorials on this site are written by Neil Coffey (@BitterCoffey). Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles, or if you simply have a programming question that you would like to see answered on this site. Most topics will be considered. But in particular, the site aims to provide tutorials and information on topics that aren't well covered elsewhere, or on Java performance information that is poorly described or understood. Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Neil Coffey 2014. All rights reserved.