| Threads of Control

## The notifyAll() and wait() Methods

> The `get()` and `put()` methods in the CubbyHole object both make use of the `notifyAll()` and `wait()` methods to coordinate getting and putting values into the CubbyHole. Both `notifyAll()` and `wait()` are members of the java.lang.Object class.

> Note: The `notifyAll()` and `wait()` methods can be invoked only by the thread that holds the lock.

> Let's investigate CubbyHole's use of the `notifyAll()` method by looking at the `get()` method.

> #### The notifyAll() method

> > The `get()` method calls `notifyAll()` as the last thing it does (besides return). The `notifyAll()` method notifies all the threads waiting on the monitor held by the current thread and wakes them up. Typically, one of the waiting threads will grab the monitor and proceed.

> > In the case of the Producer/Consumer example, the Consumer thread calls the `get()` method, so the Consumer thread holds the monitor for the CubbyHole during the execution of `get()`. At the end of the `get()` method, the call to `notifyAll()` wakes up the Producer thread that is waiting to get the CubbyHole's monitor. Now, the Producer thread can get the CubbyHole monitor and proceed.

> > >     public synchronized int get() {
> > >         while (available == false) {
> > >             try {
> > >                 wait();
> > >             } catch (InterruptedException e) {
> > >             }
> > >         }
> > >         available = false;
> > >         notifyAll();           // notifies Producer
> > >         return contents;
> > >     }

> > If multiple threads are waiting for a monitor, the Java runtime system chooses one of the waiting threads to run, making no commitments or guarantees about which thread will be chosen.

> > The `put()` method works in a similar fashion to `get()`, waking up the Consumer thread that is waiting for the Producer to release the monitor.

> > The Object class has another method--`notify()`--that arbitrarily wakes up one of the threads waiting on the monitor. In this situation, each of the remaining waiting threads continues to wait until the monitor is relinquished and it is chosen by the runtime system. The use of `notify()` can be ill-conditioned, that is, it can fail when the conditions are changed just a little. Solutions based on `notifyAll()` tend to be more robust. A programmer who is not going to analyze a multi-threaded program sufficiently carefully is better off using `notifyAll()`.

> #### The wait() method

> > The `wait()` method causes the current thread to wait (possibly forever) until another thread notifies it of a condition change. You use `wait()` in conjunction with `notify()` or `notifyAll()` to coordinate the activities of multiple threads using the same resources.

> > The `get()` method contains a `while` statement that loops until `available` becomes `true`. If `available` is false--the Producer has not yet produced a new number and the Consumer should wait--the `get()` method calls `wait()`.

> > The `while` loop contains the call to `wait()`. The `wait()` method waits indefinitely for a notification from the Producer thread. When the `put()` method calls `notifyAll()`, a Consumer wakes up from the wait state and continues within the while loop. Presumably, the Producer has generated a new number and the `get()` method drops out of the while loop and proceeds. If the Prodcuer had not generated a number, `get()` goes back to the beginning of the loop and continues to wait until the Producer generates a new number and calls `notifyAll()`.

> > >     public synchronized int get() {
> > >         while (available == false) {
> > >             try {
> > >                 wait();          // waits for notifyAll() call from Producer
> > >             } catch (InterruptedException e) {
> > >             }
> > >         }
> > >         available = false;
> > >         notifyAll();
> > >         return contents;
> > >     }

> > The `put()` method works in a similar fashion, waiting for the Consumer thread to consume the current value before allowing the Producer to produce a new one.

> > Besides the version used in the Producer/Consumer example, which waits indefinitely for notification, the Object class contains two other versions of the `wait()` method:

> > `wait(long timeout)`
> >   waits for notification or until the timeout period has elapsed--timeout is measured in milliseconds.
> > `wait(long timeout, int nanos)`
> >   waits for notification or until `timeout` milliseconds plus nanos nanoseconds have elapsed.

> #### Monitors and the notifyAll() and wait() Methods

> > You might have noticed a potential problem in CubbyHole's `put()` and `get()` methods. At the beginning of the `get()` method, if the value in the CubbyHole is not available (that is, the Producer has not generated a new number since the last time the Consumer consumed it), then the Consumer waits for the Producer to put a new value into the CubbyHole. So, the question arises--how can the Producer put a new value into the CubbyHole if the Consumer holds the monitor? (The Consumer holds the CubbyHole's monitor because it's within the synchronized method `get()`.)

> > Similarly, at the beginning of the `put()` method, if the value in the CubbyHole has not yet been consumed, then the Producer waits for the Consumer to consume the value in the CubbyHole. And again the question arises--how can the Consumer consume the value in the CubbyHole, if the Producer holds the monitor? (The Producer holds the CubbyHole's monitor because it's within the synchronized method `put()`.)

> > Well, the designers of the Java language thought of this too. When the thread enters the `wait()` method, which happens at the beginning of both the `put()` and `get` methods, the monitor is released atomically, and when the thread exits the `wait()` method, the monitor is acquired again. This gives the waiting object the opportunity to acquire the monitor and, depending on who's waiting, consume the value in the CubbyHole or produce a new value for the CubbyHole.

| Threads of Control