Skip to content

Commit 53e397b

Browse files
committed
Add deadlock sample application
1 parent 62c5ec5 commit 53e397b

File tree

5 files changed

+184
-0
lines changed

5 files changed

+184
-0
lines changed

deadlock/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
Sample to a deadlock in Java Application
2+
===========================================
3+
4+
This sample application shows an example of a deadlock. Following is the definition of "deadlock" according to
5+
[Java Tutorial](https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html)
6+
7+
> Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.
8+
9+
In this application, there are two threads trying to acquire two locks.
10+
11+
### How to run
12+
13+
The application will throw Out of Memory error after some time when you run following command
14+
15+
`java -Xms1g -Xmx1g -jar target/deadlock.jar`
16+
17+
### How to detect a deadlock
18+
19+
Take a thread dump (using `jstack <pid>` command or `jcmd <pid> Thread.print`).
20+
21+
The thread dump should show the Java level deadlock details as follows.
22+
23+
```
24+
Found one Java-level deadlock:
25+
=============================
26+
"Thread Group 1-2":
27+
waiting to lock monitor 0x00007f8ab4003a78 (object 0x00000000eaca1488, a java.lang.Object),
28+
which is held by "Thread Group 1-1"
29+
"Thread Group 1-1":
30+
waiting to lock monitor 0x00007f8ab4006518 (object 0x00000000eaca1498, a java.lang.Object),
31+
which is held by "Thread Group 1-2"
32+
33+
Java stack information for the threads listed above:
34+
===================================================
35+
"Thread Group 1-2":
36+
at com.github.chrishantha.sample.deadlock.DeadlockApplication$SampleLockThread.run(DeadlockApplication.java:54)
37+
- waiting to lock <0x00000000eaca1488> (a java.lang.Object)
38+
- locked <0x00000000eaca1498> (a java.lang.Object)
39+
"Thread Group 1-1":
40+
at com.github.chrishantha.sample.deadlock.DeadlockApplication$SampleLockThread.run(DeadlockApplication.java:54)
41+
- waiting to lock <0x00000000eaca1498> (a java.lang.Object)
42+
- locked <0x00000000eaca1488> (a java.lang.Object)
43+
44+
Found 1 deadlock.
45+
```

deadlock/pom.xml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
# Copyright 2018 M. Isuru Tharanga Chrishantha Perera
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19+
20+
<parent>
21+
<groupId>com.github.chrishantha.sample</groupId>
22+
<artifactId>java-samples</artifactId>
23+
<version>0.0.2-SNAPSHOT</version>
24+
<relativePath>../pom.xml</relativePath>
25+
</parent>
26+
27+
<modelVersion>4.0.0</modelVersion>
28+
<artifactId>deadlock</artifactId>
29+
<packaging>jar</packaging>
30+
<name>deadlock</name>
31+
32+
<dependencies>
33+
<dependency>
34+
<groupId>com.github.chrishantha.sample</groupId>
35+
<artifactId>base</artifactId>
36+
</dependency>
37+
</dependencies>
38+
39+
<build>
40+
<plugins>
41+
<plugin>
42+
<groupId>org.apache.maven.plugins</groupId>
43+
<artifactId>maven-shade-plugin</artifactId>
44+
</plugin>
45+
</plugins>
46+
</build>
47+
</project>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2018 M. Isuru Tharanga Chrishantha Perera
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.github.chrishantha.sample.deadlock;
17+
18+
import com.beust.jcommander.Parameter;
19+
import com.github.chrishantha.sample.base.SampleApplication;
20+
21+
public class DeadlockApplication implements SampleApplication {
22+
23+
@Parameter(names = "--count", description = "Number of deadlocks")
24+
private int count = 1;
25+
26+
@Parameter(names = "--delay", description = "Delay in milliseconds to start a new thread group")
27+
private int delay = 0;
28+
29+
private static class SampleLockThread extends Thread {
30+
31+
private final Object lock1;
32+
private final Object lock2;
33+
34+
public SampleLockThread(final String name, final Object lock1, final Object lock2) {
35+
super(name);
36+
this.lock1 = lock1;
37+
this.lock2 = lock2;
38+
}
39+
40+
@Override
41+
public void run() {
42+
System.out.format("%s: Acquiring lock : %s%n", getName(), lock1);
43+
synchronized (lock1) {
44+
System.out.format("%s: Acquired lock : %s%n", getName(), lock1);
45+
try {
46+
Thread.sleep(100);
47+
} catch (InterruptedException e) {
48+
e.printStackTrace();
49+
}
50+
51+
System.out.format("%s: Acquiring lock : %s%n", getName(), lock2);
52+
synchronized (lock2) {
53+
System.out.format("%s: Acquired lock : %s%n", getName(), lock2);
54+
55+
}
56+
}
57+
}
58+
}
59+
60+
@Override
61+
public void start() {
62+
final String nameFormat = "Thread Group %2d-%d";
63+
for (int i = 1; i <= count; i++) {
64+
final Object lock1 = new Object();
65+
final Object lock2 = new Object();
66+
SampleLockThread t1 = new SampleLockThread(String.format(nameFormat, i, 1), lock1, lock2);
67+
SampleLockThread t2 = new SampleLockThread(String.format(nameFormat, i, 2), lock2, lock1);
68+
t1.start();
69+
t2.start();
70+
if (delay > 0) {
71+
try {
72+
Thread.sleep(delay);
73+
} catch (InterruptedException e) {
74+
e.printStackTrace();
75+
}
76+
}
77+
}
78+
}
79+
80+
@Override
81+
public String toString() {
82+
StringBuilder builder = new StringBuilder();
83+
builder.append("DeadlockApplication [count=");
84+
builder.append(count);
85+
builder.append(", delay=");
86+
builder.append(delay);
87+
builder.append("]");
88+
return builder.toString();
89+
}
90+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.github.chrishantha.sample.deadlock.DeadlockApplication

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<module>latencies</module>
5050
<module>allocations</module>
5151
<module>memoryleak</module>
52+
<module>deadlock</module>
5253
</modules>
5354

5455
<dependencyManagement>

0 commit comments

Comments
 (0)