Deadlock is a programming situation where two or more threads are blocked forever, this situation arises with at least two threads and two or more resources.
Here I have written a simple program that will cause deadlock scenario and then we will see how to analyze it.
Here is a simple Java Example:
package com.crunchify.tutorials; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; /** * @author Crunchify.com * */ public class CrunchifyThreadDeadLock { public static void main(String[] args) throws InterruptedException { Object obj1 = new Object(); Object obj2 = new Object(); Object obj3 = new Object(); Thread crunchifyThread1 = new Thread(new CrunchifySynchronizeThread(obj1, obj2), "crunchifyThread1"); Thread crunchifyThread2 = new Thread(new CrunchifySynchronizeThread(obj2, obj3), "crunchifyThread2"); Thread crunchifyThread3 = new Thread(new CrunchifySynchronizeThread(obj3, obj1), "crunchifyThread3"); crunchifyThread1.start(); Thread.sleep(3000); crunchifyThread2.start(); Thread.sleep(3000); crunchifyThread3.start(); } } class CrunchifySynchronizeThread implements Runnable { private Object obj1; private Object obj2; public CrunchifySynchronizeThread(Object obj1, Object obj2) { this.obj1 = obj1; this.obj2 = obj2; } @Override public void run() { String name = Thread.currentThread().getName(); synchronized (obj1) { System.out.println(name + " acquired lock on Object1: " + obj1); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2) { System.out.println(name + " acquired lock on Object2: " + obj2); } System.out.println(name + " released lock on Object2: " + obj2); } System.out.println(name + " released lock on Object1: " + obj1); System.out.println(name + " Finished Crunchify Deadlock Test."); } }
Output:
crunchifyThread1 acquired lock on Object1: java.lang.Object@59e3bddb crunchifyThread2 acquired lock on Object1: java.lang.Object@294e430c crunchifyThread3 acquired lock on Object1: java.lang.Object@246972f1
While your app is hanging like in the example above, you can get a thread dump and see the deadlocked threads.
For example, on Mac, you can either do Ctrl-\
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:
"crunchifyThread3" java.lang.Thread.State: RUNNABLE at sun.management.ThreadImpl.getThreadInfo1(Native Method) at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:174) at com.crunchify.tutorials.CrunchifySynchronizeThread.getThreadDump(CrunchifyThreadDeadLock.java:64) at com.crunchify.tutorials.CrunchifySynchronizeThread.run(CrunchifyThreadDeadLock.java:50) at java.lang.Thread.run(Thread.java:722) "crunchifyThread2" java.lang.Thread.State: BLOCKED at com.crunchify.tutorials.CrunchifySynchronizeThread.run(CrunchifyThreadDeadLock.java:53) at java.lang.Thread.run(Thread.java:722) "crunchifyThread1" java.lang.Thread.State: BLOCKED at com.crunchify.tutorials.CrunchifySynchronizeThread.run(CrunchifyThreadDeadLock.java:53) at java.lang.Thread.run(Thread.java:722) "Signal Dispatcher" java.lang.Thread.State: RUNNABLE "Finalizer" java.lang.Thread.State: WAITING at java.lang.Object.wait(Native Method) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189) "Reference Handler" java.lang.Thread.State: WAITING at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:503) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
Noticed here BLOCKED and WAITING threads => Deadlock
situation here.. In next example will provide simple Java Program to generate above thread dump programmatically.