Java Reference
In-Depth Information
public void someMethod_3() {
synchronized(objectRef) {
while (some condition is true) {
objectRef.wait();
}
if (some other condition is true) {
// Notify all waiting threads
objectRef.notifyAll();
}
}
}
}
Once a thread is woken up in the wait set, it has to compete with the threads in the entry set to acquire the monitor
lock of the object. After a thread is woken up in the wait set and acquires the object's monitor lock, it has choices: to do
some work and release the lock by invoking the wait() method (release and wait) again, or release the lock by exiting
the synchronized section (release and exit). One important point to remember about the call to the wait() method is
that, typically, a call to the wait() method is placed inside a loop. Here is the reason why it is necessary to do so. A thread
looks for a condition to hold. It waits by calling the wait() method and placing itself in the wait set if that condition does
not hold. The thread wakes up when it is notified by another thread, which calls the notify() or notifyAll() method.
When the thread that woke up acquires the lock, the condition that held at the time of notification may not still hold.
Therefore, it is necessary to check for the condition again, when the thread wakes up and acquires the lock, to make
sure the condition it was looking for is true, and it can continue its work. For example, consider the producer/consumer
problem. Suppose there is one producer and many consumers. Suppose a consumer calls the wait() method as
if (buffer is empty) {
buffer.wait();
}
buffer.consume();
Suppose the buffer is empty and all consumers are waiting in the wait set. The producer produces some data and
it calls the buffer.notifyAll() method to wake up all consumer threads in the wait set. All consumer threads wake
up; however, only one will get a chance to acquire the monitor lock next. The first one acquires the lock and executes
the buffer.consume() method to empty the buffer. When the next consumer acquires the monitor lock, it will also
execute the buffer.consume() statement. However, the consumer that woke up and acquired the lock before this one
had already emptied the buffer. The logical mistake in the above snippet of code is that the call to the wait() method
is placed inside an if statement instead of inside a loop. That is, after a thread wakes up, it is not checking if the buffer
contains some data or not, before trying to consume the data. The corrected snippet of code is the following:
while (buffer is empty) {
buffer.wait();
}
buffer.consume();
Search WWH ::




Custom Search