Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
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
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.
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.