I wrote a test app that should never stop. It issues t.wait()
(t
is a Thread
object), but I never call notify. Why does this code end?
Despite the main thread synchronizing on t
, the spawned thread runs, so it doesn't lock this object.
public class ThreadWait {
public static void main(String sArgs[]) throws InterruptedException {
System.out.println("hello");
Thread t = new MyThread();
synchronized (t) {
t.start();
Thread.sleep(5000);
t.wait();
java.lang.System.out.println("main done");
}
}
}
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
java.lang.System.out.println("" + i);
try {
Thread.sleep(500);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
The result is that the main thread waits 5 seconds and during this time worker gives its output. Then after 5 seconds are finished, the program exits. t.wait()
does not wait. If the main thread wouldn't sleep for 5 seconds (commenting this line), then t.wait()
would actually wait until the worker finishes. Of course, join()
is a method to use here, but, unexpectedly, wait()
does the same thing as join()
. Why?
Maybe the JVM sees that, since only one thread is running, there is no chance to notify the main thread and solves the deadlock. If this is true, is it a documented feature?
I'm testing on Windows XP, Java 6.
So, when wait() method is called by a thread, then it gives up the lock on that resource and goes to sleep until some other thread enters the same monitor and invokes the notify() or notifyAll() method.
Java Thread notify() method This method gives the notification for only one thread which is waiting for a particular object. If we use notify() method and multiple threads are waiting for the notification then only one thread get the notification and the remaining thread have to wait for further notification.
Hence, wait() and notify() methods are defined in Object class rather than Thread class. If wait() and notify() were on the Thread instead then each thread would have to know the status of every other thread and there is no way to know thread1 that thread2 was waiting for any resource to access.
wait() causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0). The current thread must own this object's monitor.
You're waiting on a Thread
- and while most objects aren't implicitly notified, a Thread
object is notified when the thread terminates. It's documented somewhere (I'm looking for it...) that you should not use wait
/notify
on Thread
objects, as that's done internally.
This is a good example of why it's best practice to use a "private" object for synchronization (and wait/notify) - something which only your code knows about. I usually use something like:
private final Object lock = new Object();
(In general, however, it's cleaner to use some of the higher-level abstractions provided by java.util.concurrent if you can. As noted in comments, it's also a good idea to implement Runnable
rather than extending Thread
yourself.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With