Java: Notify() VS. Notifyall() All Over Again

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

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.

Difference between notify() and notifyAll()

I found what is going on with my program. The three Threads print the result even with the notify(), because they do not manage to enter the waiting state. The calculation in the widThread is performed quickly enough to preempt the entering of the other Threads in the waiting state, since it depends on the condition mw.getSum() == 0 (while loop). The widThread calculates the sum, so that the remaining Threads do not ever "see" its value as 0.
If the while loop is removed and the start of widThread comes after the start of the other Threads, then by notify() only one Thread prints the result and the others are waiting forever, as the theory and the other answers indicate.

Java - notify() vs notifyAll() - possible deadlock?

Yes. Imagine you implement the Producer - Consumer problem with synchronize, wait, and notify. (edit) In which 2 Producers and 2 Consumers all wait on the same object monitor (end edit).The Producer calls notify in this implementation. Now suppose you have two Threads running the Producer's code path. It is possible that Producer1 calls notify and wakes Producer2. Producer2 realizes he can not do any work and subsequently fails to call notify. Now you are deadlocked.

(edit) Had notifyAll been called, then both Consumer1 and Consumer2 would have woken up in addition to Producer2. One of the Consumers would have consumed the data and in turn called notifyAll to wake up at least one Producer, thus allowing the very broken implementation to limp along successfully.

Here is the reference question I base my scenario off of:
My Produce Consumer Hangs

Threads notifyAll()

When executing multiple threads, order of execution of the threads is not guaranteed.

In your case chances are that the Calculator thread completes it's loop and calls notifyAll() even before any of the Reader threads gets into runnable state. So all Reader will keep waiting and will never print total.

To avoid such situation, in this particular example you can use another flag isCalculated in Calculator and set this flag once computation is done. Reader threads will also check for this flag and wait only when isCalculated is false.

class Reader extends Thread {
Calculator c;

public Reader(Calculator calc) {
c = calc;
}

public void run() {
synchronized (c) {
try {
System.out.println("Waiting for calculation...");

if (!c.isCalculated) { // wait only if calculation is not done
c.wait();
}
} catch (InterruptedException e) {
}
System.out.println("Total is: " + c.total);
}
}
}

class Calculator implements Runnable {
int total;
boolean isCalculated;

public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}

isCalculated = true; // set flag to mark that computation is complete
notifyAll();
}
}
}

What happens on notifyAll()?

The answers to the linked question don't address these points specifically.

The threads that are notified with notifyAll get woken up, then they try to acquire the lock they were blocked waiting on (along with any newly-arrived threads that want to acquire the lock). The scheduler picks a winner, and the losers go back to blocking again.

The OS thread does not get reassigned away from the Java thread object, the OS-level thread blocks. You can confirm this by watching the threads in a performance monitoring tool. Scheduling and blocking are all occurring at the OS level (except for green threads, where threads are simulated by the JVM).



Related Topics



Leave a reply



Submit