Exercise 1.4: Resolving the thread bottleneck

Before you begin, you must complete Exercise 1.3: Identifying a thread bottleneck.

To locate the deadlock in your code, you can use the UML2 Sequence Diagram (the Object Interactions and Thread Interactions views) and the Call Stack View, in addition to the Thread View.

To resolve this deadlock, let's first find out which method calls and which objects are involved in the problem:

  1. In the Thread View, find the first philo* thread that enters a "Deadlock" state. Pause your cursor over the "Deadlock" segment. The tool tip identifies the lock (Fork.<id number>)and the locking thread (Locking Thread.<name>), for example:

Lock: Fork 10038
Locking Thread: philo#1

  1. Right-click the Profiling resource for the run and select Open With > UML2 Object Interactions. The UML2 Sequence Diagram view opens, displaying Object Interactions.
  2. In the sequence diagram, scroll the view horizontally to find Fork.<id number> and click to select it.

Sequence Diagram showing object interactions

  1. Scroll down to find a horizontal arrow from one of the philo* threads to Fork.<id number>. These arrows show interactions between objects, and the first interaction between these two objects will indicate that the philo* thread has acquired Fork.<id number>. You'll find such an arrow labeled getName.

Sequence Diagram showing getName

  1. Click getName. In the Thread View, the vertical Current Time indicator moves to show to see what was happening in the entire program when getName was called. You can see that the request was successful, as the philo* thread that is making the request is not yet in the "Waiting for Lock" or "Deadlock" state.

Thread View showing the philo* thread in the running state

  1. In the sequence diagram, click Fork.<id number> again, and scroll down to find a getName request that originated in a different philo* thread.
  2. Click this instance of getName. The Current Time indicator will show that the philo* thread making the request does not get Fork.<id number>, and enters a "Waiting for Lock" and then "Deadlock" state.

In this instance, a request for a Fork that is held by another thread is the problem. Check other threads that are deadlocked to verify that this is true in other instances as well.

Now let's try to find the method that is causing the problem:

  1. Right-click the Profiling resource for the run and select Open With > UML2 Thread Interactions. The UML2 Sequence Diagram view opens, displaying Thread Interactions.
  2. In the Thread View, click the menu drop-down button and click Open Call Stack View.
  3. In the Thread View, where the names of threads are displayed, double-click the first of the deadlocked philo* threads. Notice that the Thread Interactions view changes to display information for only that thread.
  4. Scroll down to the end of the information for the thread and double-click the last method that the thread ran: the run method. The Call Stack View displays all the calls on the stack at that time.
  5. In the Call Stack, note that the thread that is holding the lock has called the Sleep method in Philosopher.java; or that it is also deadlocked and consequently doing nothing.
  6. Check the other threads that end the run in a deadlocked state; the Sleep method in Philosopher.java is often in the Call Stack and may be the problem.

We now suspect the Sleep method. Let's have a look at the code:

  1. In the Call Stack, right-click an instance of Sleep(int) void [Philosopher.java] and select Open source. The source opens in the editor at the location of the Sleep class.
  2. Examine the code. Note that the Sleep method is called by the run method. There is first a call to trace, which prints out the message "got left...", and then a call to Sleep. By commenting out the call to Sleep, we can possibly prevent the deadlock.
  3. Comment out Sleep.
  4. Select File > Save.
Now profile your program again.

This time it runs without a deadlock and writes to the console:

HeadWaiter reports all philosophers have finished dining normally

As you can see, the Thread View and the other views show you what happens to the threads as your program runs. It's up to you to perform the analysis and resolve the deadlock, based on your knowledge of your program.

Finish your tutorial by reviewing the materials in the Summary.

Feedback
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.