Java Reference
In-Depth Information
Figure 15.11 The DeadlockDemo program locks up and does not generate any further
output than what is shown here.
The problem with the LazyTeller class is that it does not consider the possi-
bility of a race condition, a common occurrence in multithreaded program-
ming. After the two threads are started, teller1 grabs the checking lock and
teller2 grabs the savings lock. When teller1 tries to obtain the savings lock, it is
not available. Therefore, teller1 blocks until the savings lock becomes avail-
able. When the teller1 thread blocks, teller1 still has the checking lock and does not
let it go . Similarly, teller2 is waiting for the checking lock, so teller2 blocks but
does not let go of the savings lock . This leads to one result: deadlock! The two
threads are now blocked forever, and the only way to end this application is to
terminate the JVM.
There is a solution to this problem with the race condition. Whenever a
thread needs more than one lock, the thread should be careful not to simply
randomly grab the locks. Instead, all threads involved need to agree on a spec-
ified order in which to to obtain the locks so that deadlock can be avoided. Let
me show how this is done.
Ordering Locks
A common threading trick to avoid the deadlock of the LazyTeller threads is to
order the locks. By ordering the locks, it gives threads a specific order to obtain
multiple locks. For example, when transferring money, instead of a bank teller
obtaining the lock of the source account first, the teller could grab the account
with the smaller number first (assuming that each bank account has a unique
number). This ensures that whoever wins the race condition (whichever teller
obtains the lower account number first), that thread can continue and obtain
further locks, whereas other threads block without taking locks with them.
The following transfer() method, in a class named OrderedTeller, is a modi-
fication of the LazyTeller class. Instead of arbitrarily synchronizing on locks,
this transfer() method obtains locks in a specified order based on the number
of the bank account.
public class OrderedTeller extends Thread
{
private ThreadSafeBankAccount source, dest;
public OrderedTeller(ThreadSafeBankAccount a,
Search WWH ::




Custom Search