Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Diagnose common runtime problems with hprof

Track down the culprits behind your application failures

  • Print
  • Feedback

Page 5 of 6

Note: hprof's cpu=time mode should show CPU usage hierarchically, but this feature appears to have a bug that leads to a segmentation fault in the 1.3 VMs I worked with.

Diagnose a deadlock

The third control program exhibits a classic deadlock, as shown in Listing 3:

Listing 3. Deadlock program

01 /** Main class for the control test. */
02 public class ClassicDeadlock {
03 
04    public static void main(String[] args) {
05       SynchronizedObject left;
06       SynchronizedObject right;
07 
08       LeftToRightGrabber leftToRight;
09       RightToLeftGrabber rightToLeft;
10 
11       left  = new SynchronizedObject("left");
12       right = new SynchronizedObject("right");
13 
14       leftToRight = new LeftToRightGrabber(left,right);
15       rightToLeft = new RightToLeftGrabber(left,right);
16 
17       leftToRight.start();
18       rightToLeft.start();
19    }
20 
21 } // End ClassicDeadlock.
22 
23 /** An object containing a synchronized method. */
24 class SynchronizedObject {
25   public String name;
26   public SynchronizedObject(String aName) {
27      name = aName;
28   }
29   public synchronized void synchronizedMethod() {
30       String message = name                        + 
31                        " lock acquired by thread " +
32                        Thread.currentThread().getName(); 
33       System.out.println(message);
34       System.out.flush();
35   }
36 } // End of SynchronizedObject.
37 
38 /** Base class for the Left and Right Grabber. */
39 abstract class GrabberBase extends Thread {
40    protected SynchronizedObject leftObject;
41    protected SynchronizedObject rightObject;
42 
43    public GrabberBase(SynchronizedObject left,
44                       SynchronizedObject right,
45                       String             name
46                      ) {
47      super(name);
48      leftObject  = left;
49      rightObject = right; 
50    } 
51 } // End of GrabberBase.
52 
53 /** Class to grab locks right and then left. */
54 class RightToLeftGrabber extends GrabberBase {
55       public RightToLeftGrabber( SynchronizedObject left,
56                                  SynchronizedObject right) {
57           super(left, right, "RightToLeft");
58       }
59 
60       public void run() {
61          while(true) {
62            grabRightToLeft();
63          }
64       }
65 
66       private void grabRightToLeft() {
67           synchronized (rightObject) {
68              leftObject.synchronizedMethod();
69           }
70       }
71 } // End of RightToLeftGrabber.
72 
73 /** Class to grab locks left and then right. */
74 class LeftToRightGrabber extends GrabberBase {
75       public LeftToRightGrabber( SynchronizedObject left,
76                                  SynchronizedObject right) {
77           super(left, right, "LeftToRight");
78       }
79 
80       public void run() {
81          while(true) {
82             grabLeftToRight();
83          }
84       }
85  
86       private void grabLeftToRight() {
87           synchronized (leftObject) {
88              rightObject.synchronizedMethod();
89           }
90       }
91 } // End of LeftToRightGrabber.


This program creates two equivalent objects, left and right, each having its own synchronization monitor. Two threads then try to grab locks on these objects in a particular order (by entering a block synchronized on one object and then calling a synchronized method on the other). If the LeftToRightGrabber thread can enter its synchronized block and the RightToLeftGrabber thread is scheduled to run before LeftToRightGrabber completes its work, a deadlock will occur. How long the program must run to hit a deadlock depends on the JVM's thread scheduling algorithm. For me, this typically occurred during the third switch between thread contexts.

  • Print
  • Feedback

Resources