Some times threads need some condition to be realized by other threads to
continue execution. Until this condition is realized a thread should make
continues wait and check. But this means waste of resources and since thread
probably owns lock that is needed by other threads to realize this condition, may
lead to deadlocks. Java has a better alternative. Java Object class has wait/notify/notifyAll
methods to deal with such situations. A
complete example of wait/notify idiom is given below.
class ProducerConsumer {
List dataList = new ArrayList();
boolean empty = true;
synchronized void produce() {
dataList.add(new Object());
empty = false;
notifyAll();// notify waiting
threads
}
synchronized void consume() {
while (empty)
try {
wait(); // wait until
notifyAll is called
} catch (InterruptedException e) {}
dataList.clear();// just clear list
empty = true;
}
public static void main(String[] args) {
final ProducerConsumer prodCons
= new ProducerConsumer();
// producer thread
new Thread(
new Runnable() {
public void run() {
while (true)
prodCons.produce();
}
}
).start();
// consumer thread
new Thread(
new Runnable() {
public void run() {
while (true)
prodCons.consume();
}
}
).start();
}
}
Assume consumer thread enters consume method and sees that empty flag is
set. It calls wait on the object it has the lock of. When a thread calls wait
method it releases the locks it owns and suspends execution by entering WAITING
state until it is notified. Then producer thread enters produce method. Adds an arbitrary object to
data list and clears empty flag. Then calls notifyAll on the object it has the
lock of. All threads waiting on the lock of the object are waken up but only
one of them will be able to resume execution. Other threads, if there are any,
will continue waiting untill another notification is sent. Resuming thread will
continue its execution from the point it left.
This way, threads are coordinated and achieved to work in harmony.
Things to Note:
-
Always check
for condition inside a loop. Because notify may be sent for different
conditions other than thread is waiting for.
-
Always call
wait/notify/notifyAll methods within syncronized methods or statements. Other
wise IllegalMonitorStateException will be thrown.
-
To
wait/notify mechanism to work correctly threads must be owning the lock of the
same object.
-
Notify method
only wakes up a single thread, notiftAll on the other hand wakes up all waiting
threads (of course only all threads waiting on the lock of the object notify is
called). What happens if notify wakes up a single thread and this thread is
waiting for a different condition to be realized? It will continue waiting and
notification will be wasted. To avoid such waste, prefer notifyAll method.
Comments
Post a Comment