Why doesn't thread wait for notify()
? The thread starts and then goes to the waiting pool, but it proceeds to execute after that moment.
public class JavaApplication2 {
public static void main(String [] args) {
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
try {
System.out.println("1");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
@Override
public void run() {
synchronized(this) {
total += 1;
//notify();
}
}
}
The method
notifyAll()
is invoked for theThread
object of the terminating thread. This fact is strangely documented in the description of theThread.join
, with the following sentence:Thus, if you don't explicitly read the description of
join
, which you don't necessarily have to, you don't get to know the reason for the strange behavior.I was doing the same testing on the wait/notify opertaions while reading OCP SE 7, good catch. I think we should let the authoer to explain.
You cannot depend on not returning from wait until a notify: "interrupts and spurious wakeups are possible". In general, you should wrap a wait call in a loop while the thread should go on waiting.
You have nested synchronized {} constructs in the two places. These constructs seem doing something weird: the thread does not react into notify at all and only resumes when ThreadB (b) terminates. Remove this:
The code above probably works correctly: with notify() present the main thread resumes after 5 seconds and before we see the message that ThreadB terminates. With notify() commented out the main thread resumes after 10 seconds and after the message about the termination of the ThreadB because notify() is called anywhay from the other code. Marko Topolnik explains why and from where this "behind the scene" notify() call comes from.
If you try your code synchronizing on any object other that
ThreadB
you will find it never terminates. This is because there is a hidden call tonotify
.Although I am not aware of anywhere that this is specified, Thread notifies itself when it ends. This is implicit in the way the
join
method is implemented. This is the code forjoin
:(From the JDK7 source code)
As you can see, the calls to
wait
only make sense if somewhere there is a call tonotify
that is called after the thread ends. The same call tonotify
is what allows your program to terminate.You are synchronizing on the thread object itself, which is wrong usage. What happens is that the dying thread-of-execution always calls
notify
on itsThread
object:Thread.join
relies on this. Therefore it is clear why you get the same behavior with and without your ownnotify
in there.Solution: use a separate object for thread coordination; this is the standard practice.