Java Reference
In-Depth Information
The sequence of events is as follows:
thread1 starts first, and synchronizes on theObject . This prevents any methods for
theObject being called by any other thread.
thread1 then calls sleep() so thread2 can start.
thread2 starts and synchronizes on theOtherObject . This prevents any methods for
theOtherObject being called by any other thread.
thread2 then calls sleep() allowing thread1 another go.
thread1 wakes up and tries to call method2() for theOtherObject , but it can't until the
code block in thread2 that is synchronized on theOtherObject completes execution.
thread2 gets another go because thread1 can't proceed, and tries to call method1() for
theObject . This can't proceed until the code block in thread1 that is synchronized on
theObject completes execution.
Neither thread has any possibility of continuing - they are deadlocked. Finding and fixing this sort of
problem can be very difficult, particularly if your program is complicated and has other threads that will
continue to execute.
You can create a trivial deadlock in the last example by making the for loop in main() synchronized
on one of the accounts. For example:
synchronized(accounts[1]) {
for(int i = 1; i <= transactionCount; i++) {
// code for generating transactions etc...
}
}
A deadlock occurs as soon as a transaction for accounts[1] arises because the doTransaction()
method in the theBank object that is called by a Clerk object to handle the transaction will be
synchronized to the same object and can't execute until the loop ends. Of course, the loop can't
continue until the method in the theBank object terminates so the program hangs.
In general, ensuring that your program has no potential deadlocks is extremely difficult. If you intend to
do a significant amount of programming using threads, you will need to study the subject in much more
depth than we can deal with here. A good book on the subject is Concurrent Programming in Java: Design
Principles and Patterns written by Doug Lea (ISBN 0-201-69581-2).
Communicating between Threads
We've seen how we can lock methods or code blocks using synchronization to avoid the problems that
uncontrolled thread execution can cause. While this gives us a degree of control, we're still introducing
inefficiencies into the program. In the last example, there were several occasions where we used a loop
to wait for a clerk thread to complete an operation before the current thread could sensibly continue.
For example, we couldn't pass a transaction to a Clerk object while that object was still busy with the
previous transaction. Our solution to this was to use a while loop to test the busy status of the Clerk
object from time to time and call the sleep() method in between. But there's a much better way.
Search WWH ::




Custom Search