blob: 314750f1b378567007fbbb2b55aeba810e5a9bad [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 */
34
35import java.util.concurrent.CyclicBarrier;
36import java.util.concurrent.BrokenBarrierException;
37import java.util.concurrent.locks.Lock;
38import java.util.concurrent.locks.ReentrantLock;
39import java.io.IOException;
40
41/**
42 * This Deadlock class demonstrates the capability of performing
43 * deadlock detection programmatically within the application using
44 * the java.lang.management API.
45 *
46 * See ThreadMonitor.java for the use of java.lang.management.ThreadMXBean
47 * API.
48 */
49public class Deadlock {
50 public static void main(String[] argv) {
51 Deadlock dl = new Deadlock();
52
53 // Now find deadlock
54 ThreadMonitor monitor = new ThreadMonitor();
55 boolean found = false;
56 while (!found) {
57 found = monitor.findDeadlock();
58 try {
59 Thread.sleep(500);
60 } catch (InterruptedException e) {
61 System.exit(1);
62 }
63 }
64
65 System.out.println("\nPress <Enter> to exit this Deadlock program.\n");
66 waitForEnterPressed();
67 }
68
69
70 private CyclicBarrier barrier = new CyclicBarrier(6);
71 public Deadlock() {
72 DeadlockThread[] dThreads = new DeadlockThread[6];
73
74 Monitor a = new Monitor("a");
75 Monitor b = new Monitor("b");
76 Monitor c = new Monitor("c");
77 dThreads[0] = new DeadlockThread("MThread-1", a, b);
78 dThreads[1] = new DeadlockThread("MThread-2", b, c);
79 dThreads[2] = new DeadlockThread("MThread-3", c, a);
80
81 Lock d = new ReentrantLock();
82 Lock e = new ReentrantLock();
83 Lock f = new ReentrantLock();
84
85 dThreads[3] = new DeadlockThread("SThread-4", d, e);
86 dThreads[4] = new DeadlockThread("SThread-5", e, f);
87 dThreads[5] = new DeadlockThread("SThread-6", f, d);
88
89 // make them daemon threads so that the test will exit
90 for (int i = 0; i < 6; i++) {
91 dThreads[i].setDaemon(true);
92 dThreads[i].start();
93 }
94 }
95
96 class DeadlockThread extends Thread {
97 private Lock lock1 = null;
98 private Lock lock2 = null;
99 private Monitor mon1 = null;
100 private Monitor mon2 = null;
101 private boolean useSync;
102
103 DeadlockThread(String name, Lock lock1, Lock lock2) {
104 super(name);
105 this.lock1 = lock1;
106 this.lock2 = lock2;
107 this.useSync = true;
108 }
109 DeadlockThread(String name, Monitor mon1, Monitor mon2) {
110 super(name);
111 this.mon1 = mon1;
112 this.mon2 = mon2;
113 this.useSync = false;
114 }
115 public void run() {
116 if (useSync) {
117 syncLock();
118 } else {
119 monitorLock();
120 }
121 }
122 private void syncLock() {
123 lock1.lock();
124 try {
125 try {
126 barrier.await();
127 } catch (InterruptedException e) {
128 e.printStackTrace();
129 System.exit(1);
130 } catch (BrokenBarrierException e) {
131 e.printStackTrace();
132 System.exit(1);
133 }
134 goSyncDeadlock();
135 } finally {
136 lock1.unlock();
137 }
138 }
139 private void goSyncDeadlock() {
140 try {
141 barrier.await();
142 } catch (InterruptedException e) {
143 e.printStackTrace();
144 System.exit(1);
145 } catch (BrokenBarrierException e) {
146 e.printStackTrace();
147 System.exit(1);
148 }
149 lock2.lock();
150 throw new RuntimeException("should not reach here.");
151 }
152 private void monitorLock() {
153 synchronized (mon1) {
154 try {
155 barrier.await();
156 } catch (InterruptedException e) {
157 e.printStackTrace();
158 System.exit(1);
159 } catch (BrokenBarrierException e) {
160 e.printStackTrace();
161 System.exit(1);
162 }
163 goMonitorDeadlock();
164 }
165 }
166 private void goMonitorDeadlock() {
167 try {
168 barrier.await();
169 } catch (InterruptedException e) {
170 e.printStackTrace();
171 System.exit(1);
172 } catch (BrokenBarrierException e) {
173 e.printStackTrace();
174 System.exit(1);
175 }
176 synchronized (mon2) {
177 throw new RuntimeException(getName() + " should not reach here.");
178 }
179 }
180 }
181
182 class Monitor {
183 String name;
184 Monitor(String name) {
185 this.name = name;
186 }
187 }
188
189 private static void waitForEnterPressed() {
190 try {
191 boolean done = false;
192 while (!done) {
193 char ch = (char) System.in.read();
194 if (ch<0||ch=='\n') {
195 done = true;
196 }
197 }
198 }
199 catch (IOException e) {
200 e.printStackTrace();
201 System.exit(0);
202 }
203 }
204}