Deadlock Detection in Java

What is a deadlock?

Imagine you have two threads, thread1 and thread2. Thread1 acquires lock1 and is about to acquire lock2 while thread2 acquires lock2 and is about to acquire lock1. In this case, threads are deadlocked because they are each waiting for the other thread to release the other lock and your application just hangs. Deadlocks usually occur when the order of locks is not consistent throughout the application.

Deadlock sample with regular sync blocks

Here is a a quick sample that shows the deadlock situation explained above with good old sync blocks.

private static void test1() {
    final Object lock1 = new Object();
    final Object lock2 = new Object();
    Thread thread1 = new Thread(new Runnable() {
        @Override public void run() {
            synchronized (lock1) {
                System.out.println("Thread1 acquired lock1");
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                catch (InterruptedException ignore) {}
                synchronized (lock2) {
                    System.out.println("Thread1 acquired lock2");
                }
            }
        }
    });
    thread1.start();
    Thread thread2 = new Thread(new Runnable() {
        @Override public void run() {
            synchronized (lock2) {
                System.out.println("Thread2 acquired lock2");
                try {
                    TimeUnit.MILLISECONDS.sleep(50);
                catch (InterruptedException ignore) {}
                synchronized (lock1) {
                    System.out.println("Thread2 acquired lock1");
                }
            }
        }
    });
    thread2.start();
    // Wait a little for threads to deadlock.
    try {
        TimeUnit.MILLISECONDS.sleep(100);
    catch (InterruptedException ignore) {}
}

The sample prints the following and then just hangs due to deadlocked threads:

Thread1 acquired lock1
Thread2 acquired lock2

Manual Deadlock Detection

While your app is hanging like in the example above, you can get a thread dump and see the deadlocked threads. Or simply use jstack and process id to get the thread dump which makes it very obvious where the deadlock is. In this example, the thread dump looks like this:

Found one Java-level deadlock:
=============================
"Thread-2":
  waiting to lock monitor 102054308 (object 7f3113800, a java.lang.Object),
  which is held by "Thread-1"
"Thread-1":
  waiting to lock monitor 1020348b8 (object 7f3113810, a java.lang.Object),
  which is held by "Thread-2"

 

jstack 1234 > stack.txt

 

Java stack information for the threads listed above:
===================================================
"Thread-2":
    at DeadlockTest$2.run(DeadlockTest.java:42)
    - waiting to lock <7f3113800> (a java.lang.Object)
    - locked <7f3113810> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:680)
"Thread-1":
    at DeadlockTest$1.run(DeadlockTest.java:26)
    - waiting to lock <7f3113810> (a java.lang.Object)
    - locked <7f3113800> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:680)
Found 1 deadlock.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s