wait() and notify()

Thread Synchronization

Excerpt from old “Exploring Java” book.
It clearly states, what wait(), notify(), notifyAll() are used for and what they do.

With the synchronized keyword, we can serialize the execution of complete methods and blocks of code. The wait() and notify() methods of the Object class extend this capability. Every object in Java is a subclass of Object, so every object inherits these methods. By using wait() and notify(), a thread can give up its hold on a lock at an arbitrary point, and then wait for another thread to give it back before continuing. All of the coordinated activity still happens inside of synchronized blocks, and still only one thread is executing at a given time.

By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep. A thread might do this if it needs to wait for something to happen in another part of the application, as you’ll see shortly. Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object. Now the first thread wakes up and begins trying to acquire the lock again.

When the first thread manages to reacquire the lock, it continues from the point it left off. However, the thread that waited may not get the lock immediately (or perhaps ever). It depends on when the second thread eventually releases the lock, and which thread manages to snag it next. Note also, that the first thread won’t wake up from the wait() unless another thread calls notify(). There is an overloaded version of wait(), however, that allows us to specify a timeout period. If another thread doesn’t call notify() in the specified period, the waiting thread automatically wakes up.

Let’s look at a simple scenario to see what’s going on. In the following example, we’ll assume there are three threads–one waiting to execute each of the three synchronized methods of the MyThing class. We’ll call them the waiter, notifier, and related threads, respectively. Here’s a code fragment to illustrate:

class MyThing {

synchronized void waiterMethod() {
// Do some stuff

// Now we need to wait for notifier to do something
wait();

// Continue where we left off
}

synchronized void notifierMethod() {
// Do some stuff

// Notify waiter that we've done it
notify();

// Do more things
}

synchronized void relatedMethod() {
// Do some related stuff
}

Let’s assume waiter gets through the gate first and begins executing waiterMethod(). The two other threads are initially blocked, trying to acquire the lock for the MyThing object. When waiter executes the wait() method, it relinquishes its hold on the lock and goes to sleep. Now there are now two viable threads waiting for the lock. Which thread gets it depends on several factors, including chance and the priorities of the threads. (We’ll discuss thread scheduling in the next section).

Let’s say that notifier is the next thread to acquire the lock, so it begins to run. waiter continues to sleep and related languishes, waiting for its turn. When notifier executes the call to notify(), Java prods the waiter thread, effectively telling it something has changed. waiter then wakes up and rejoins related in vying for the MyThing lock. Note that it doesn’t actually receive the lock; it just changes from saying “leave me alone” to “I want the lock.”

At this point, notifier still owns the lock and continues to hold it until it leaves its synchronized method (or perhaps executes a wait() itself). When it finally completes, the other two methods get to fight over the lock. waiter would like to continue executing waiterMethod() from the point it left off, while unrelated, which has been patient, would like to get started. We’ll let you choose your own ending for the story.

For each call to notify(), Java wakes up just one method that is asleep in a wait() call. If there are multiple threads waiting, Java picks the first thread on a first-in, first-out basis. The Object class also provides a notifyAll() call to wake up all waiting threads. In most cases, you’ll probably want to use notifyAll() rather than notify(). Keep in mind that notify() really means “Hey, something related to this object has changed. The condition you are waiting for may have changed, so check it again.” In general, there is no reason to assume only one thread at a time is interested in the change or able to act upon it. Different threads might look upon whatever has changed in different ways.

Often, our waiter thread is waiting for a particular condition to change and we will want to sit in a loop like the following:

...
while ( condition != true )
wait();
...

Other synchronized threads call notify() or notifyAll() when they have modified the environment so that waiter can check the condition again. This is the civilized alternative to polling and sleeping, as you’ll see the following example.

Copy-pasted from here.

0 Responses to “wait() and notify()”


  • No Comments

Leave a Reply




Hosted by EOMY.NET