|
Home
Synchronization and concurrency
wait/notify
final
volatile
synchronized keyword
Java threading
Deadlock (and avoiding it)
Java 5: ConcurrentHashMap
Atomic variables
Explicit locks
Queues
Semaphores
CountDownLatch
CyclicBarrier
Have a Kindle? Sign up to the newsletter
Follow
follow the author on Twitter
RECOMMEND THIS SITE TO FRIENDS/COLLEAGUES:
Using wait(), notify() and notifyAll() in Java: common problems and mistakes
Here are some limitations and common things that go wrong with the
wait() / notify() paradigm in Java:
- You need to check the condition before entering wait(), else
you may never be notified.
- Waking up from a wait() doesn't mean the condition you were waiting for
has happened! So you generally need to wait in a loop until the condition
holds (or until you decide to give up).
- The timed wait waits forever if you pass in a zero wait time!
So be careful to check for zero if you are calculating the wait time...!
- Choosing notify() when notifyAll() is required can make threads
stall.
- Conversely, calling notifyAll() when only notify()
is required is generally benign, but may reduce program throughput.
- Calling wait() automatically releases the lock of the object you
are waiting on, but does not release locks on other
objects! So in the following case, the caller will still hold the lock
to object1 during the wait:
synchronized (object1) {
synchronized (object2) {
object2.wait();
}
}
- Calling notify() does not "transfer control" to notified
threads immediately: it merely marks them as "runnable". A notified thread will not be
able to run until the following things happen: (1) the notifying thread releases
its lock on the object being notified; (2) the thread scheduler next shcedules
the notified thread. (On some systems such as Windows, this will happen fairly quickly, because threads
are given a temporary priority boost when woken from a wait state, but it generally
won't happen until the next interrupt.)
The notify() / wait() paradigm is quite flexible, and allows
a wide variety of common synchronization constructs (queues, resource pools,
thread pools, barriers, read/write locks, semaphores...) to be created some way or other.
Until Java 5, a disadvantage of Java as a platform is that it hasn't had
library implementations of these constructs as standard. Goodness only knows how many
Java implementations of queues, semaphores and thread pools there must be out there, with
differing degrees of bugginess.
Java 5 improves this situation by providing standard library implementations of
well-tested, high performance synchronization constructs. On the next page, we'll
see an example of using wait/notify to
implement a latch, and how Java 5 provides the CountDownLatch
with this functionality.
Java programming articles and tutorials on this site are written by Neil Coffey (@BitterCoffey).
Suggestions are always welcome if you wish to suggest topics for Java tutorials or programming articles,
or if you simply have a programming question that you would like to see answered on this site. Most topics
will be considered. But in particular, the site aims to provide tutorials and information on topics that
aren't well covered elsewhere, or on Java performance information that is poorly described or understood.
Suggestions may be made via the Javamex blog (see the site's front page for details).
Copyright © Javamex UK 2012. All rights reserved.
|