views:

7402

answers:

10

If one google 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 general case) are not known to the programmer.

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

A: 

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.

Spoike
+5  A: 

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.

andyuk
+15  A: 

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.

Liedman
+1  A: 

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.

David Crow
+2  A: 

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.

+2  A: 

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

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

Steve McLeod
+3  A: 

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

A: 

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.

Abhay Bansal
A: 

Here is an example. Run it. Then change one of the notifyAll() to notify() and see what happens.

public class ProducerConsumerExample {

private static boolean Even = true;
private static boolean Odd = false;
public static void main(String[] args) {
    Dropbox dropbox = new Dropbox();
    (new Thread(new Consumer(Even, dropbox))).start();
    (new Thread(new Consumer(Odd, dropbox))).start();
    (new Thread(new Producer(dropbox))).start();

}

}

public class Dropbox {

private int number;
private boolean empty = true;
private boolean evenNumber = false;

public synchronized int take(final boolean even) {
    while (empty || evenNumber != even) {
        try {
            System.out.format("%s is waiting ... %n", even ? "Even" : "Odd");
            wait();
        } catch (InterruptedException e) {
        }
    }
    System.out.format("%s took %d.%n", even ? "Even" : "Odd", number);
    empty = true;
    notifyAll();

    return number;
}

public synchronized void put(int number) {
    while (!empty) {
        try {
            System.out.println("Producer is waiting ...");
            wait();
        } catch (InterruptedException e) {
        }
    }
    this.number = number;
    evenNumber = number % 2 == 0;
    System.out.format("Producer put %d.%n", number);
    empty = false;
    notifyAll();
}

}

import java.util.Random;

public class Consumer implements Runnable {

private final Dropbox dropbox;
private final boolean even;

public Consumer(boolean even, Dropbox dropbox) {
    this.even = even;
    this.dropbox = dropbox;
}

public void run() {
    Random random = new Random();
    while (true) {
        dropbox.take(even);
        try {
            Thread.sleep(random.nextInt(100));
        } catch (InterruptedException e) {
        }
    }
}

}

import java.util.Random;

public class Producer implements Runnable {

private Dropbox dropbox;

public Producer(Dropbox dropbox) {
    this.dropbox = dropbox;
}

public void run() {
    Random random = new Random();
    while (true) {
        int number = random.nextInt(10);
        try {
            Thread.sleep(random.nextInt(100));
            dropbox.put(number);
        } catch (InterruptedException e) {
        }
    }
}

}

Erik
+1  A: 
xagyg
There is an alternative: if the woken thread (P3 in your example) does not detect the condition it is interested in then it calls `notify()` again. That way `notify()` is called as many times as necessary until one thread is able to proceed.
finnw
finnw - P3 must re-check the condition because the `notify` causes P3 (the selected thread in this example) to proceed from the point it was waiting (i.e. within the `while` loop). There are other examples that do not cause deadlock, however, in this case the use of `notify` does not guarantee deadlock-free code. The use of `notifyAll` does.
xagyg
@xagyg, the condition must be repeatedly checked until there is a char in the buffer, but it can either be the same thread (in a wait/check loop) or a cycle of threads notifying each other until one finds a char in the buffer.
finnw