Does notify/notifyall release the lock being held
wait( ) tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
notify( ) wakes up a thread that called wait( ) on the same object.
notifyAll( ) wakes up all the threads that called wait( ) on the same object. The highest priority thread will run first.
No -- notify
/notifyAll
don't release locks like wait
does. The awakened thread can't run until the code which called notify
releases its lock.
This is what the Javadoc says:
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
I have to disagree with people who say notifyAll()
releases the lock on the object over which waiting and notifying threads are being synchronized.
An example:
Consumer
class contains a block:
synchronized(sharedObject){
if(sharedObject.isReadyToConsume() == false){
sharedObject.wait();
}else {
sharedObject.doTheThing();
System.out.println("consumer consuming...");
}
}
Scenario: Consumer class gets the lock on the sharedObject object, enters exclusively (it's inside the sync block) and sees that sharedObject has nothing ready yet (nothing to consume :) ) and it calls wait()
method on the sharedObject. That way it releases the lock (stops the execution there!) and waits to be notified to continue when another Thread (Producer maybe) calls sharedObject.notify();
or sharedObject.notifyAll();
. When it gets notified it continues from the wait() line
It's the sharedObject that keeps track of threads that asked it to be notified. When some Thread calls sharedObject.notifyAll() method the sharedObject will notify the waiting threads to wake up... Now, the tricky part is that a thread naturally releases the lock of the object when it reaches the end of its synchronized(sharedObject){} block. THe question is what happens if I call notifyAll() in that block??? notifyAll() wakes up the waiting threads, but the lock is still owned by the Thread that has just call notifyAll()
Look at the Producer snippet:
synchronized(sharedObject){
//We are exlusively working with sharedObject and noone can enter it
[... changing the object ...]
sharedObject.notifyAll(); //notifying the waiting threads to wake up
Thread.sleep(1000); //Telling the current thread to go to sleep. It's holding the LOCK
System.out.println("awake...");
}
If notifyAll() would release the lock then the "awake..." would get printed out after the Consumer classes already start working with the sharedObject. This is not the case... The output shows that the Consumer is consuming the sharedObject after the Producer exits its sync block...
- wait() - releases the lock and continues on the next line when it gets notified
- notify(), notifyAll() - don't release the lock. They simply make waiting threads runnable again (not idle). They will have the right to enter when the current thread reaches the end of its sync block and the Thread scheduleder tells them that the lock has been released. The fight for the lock begins again