of the JVM, the performance numbers would turn around completely! Always use
wait()/notifyAll() unless you have a very specific need for condition variables.
Coarse vs. Fine Grain Locking
At what level do you put your locks? You could have one big lock that covered everything, and
then any time any thread wanted to access any shared data, it would need that one lock. This
would be a good thing because you would not lock it very often. This would be bad because you'd
be holding it for a long time.
You could do exactly the opposite and use a different lock for every set of variables, locking and
unlocking them quite often. This would be a good thing because the locks would be free most of
the time and you could get lots of concurrent operations. It would be bad because you would
spend a lot of time in locking and unlocking overhead.
In small programs this may not be an issue. In larger programs it's quite likely that you'll choose
different levels of granularity for different sections. In Manipulating Lists we show a small search
and update program that demonstrates this trade-off.
What to Lock
Closely related to the question of granularity is the question of what you want to protect. In the
simple case, it's pretty obvious. You want to protect a queue? You lock the queue object every
time you do anything with the queue. That's easy. Folks sometimes get confused when they're
changing several things concurrently. What if you wanted to add items to your queue and you also
wanted to change the pointer to the queue itself? In this scenario it is highly likely that your lock
on the queue object would be counterproductive, because it would make you think you were
protecting the queue (which of course you are), whereas what you really needed to do was to
protect the variable that pointed to the queue.
Let's look at a more likely scenario. Let's assume that you have a queue of people and you want to
do very fine grained locking on that queue by locking each individual element of that queue
(instead of having one big lock protecting the entire queue). This is a perfectly reasonable thing to
do and in some cases is the most efficient method of locking a structure. (We'll look at the
The question we want to answer here is "What should I lock?" We can point you to many
examples of programs where people have locked the wrong thing. In Figure 7-7 we see a queue of
people and their salaries. Each person object also contains a lock. What does that lock protect? It
can protect pretty much anything you want it to (you're the programmer), except for itself or the
object that contains it.
Figure 7-7. Friends/Enemies with Only One Local Mutex Lock
Search WWH :