Deadlock in Java

In a multi-threaded environment there may come a situation when one thread is waiting for a resource that is locked by another thread, which in turn is waiting for another thread and so on until this dependency loops back to the first waiting thread. Thus all the threads are waiting for each other to release the resources to make any further progress and blocked forever in the process. This scenario is called deadlock in multi-threading.

Deadlock example

To explain deadlock in Java we can take a simple scenario of two threads Thread1 and Thread2, where Thread1 holds a lock on obj1 and waiting to acquire a lock on obj2. At the same time Thread2 has a lock on obj2 and waiting to acquire lock on obj1. Here both threads are blocked in a circular loop where Thread1 is waiting to acquire lock on obj2 and Thread2 is waiting to acquire lock on obj1 thus creating a deadlock.

Deadlock in Java

Deadlock in Java

Deadlock in Java scenarios

You may get deadlock in Java because of the improper use of the synchronized keyword. Scenarios when deadlock may happen are as follows.

  1. Nested synchronized blocks with reverse ordering of objects.
  2. Calling one synchronized method from another where methods are not using the same object to synchronize.

DeadLock in Java example code

First example shows the scenario when there are nested synchronized blocks with reverse ordering of objects.

Output

In ThreadA’s run method synchronization is first done on obj1 and later on obj2. In ThreadB’s run method synchronization is reversed, it is first done on obj2 and later on obj1. That may result in a deadlock where t1 gets a lock on obj1 and waiting to acquire a lock on obj2. At the same time obj2 has acquired a lock on obj2 and waiting to acquired a lock on obj1.

Another deadlock Java example shows the scenario where one synchronized method is called from another.

Output

In the code there are two instances of DLDemo class, one thread calls the synchronized method method1 using obj1 and another thread calls it using obj2. Which means Thread1 holds a lock on obj1 and Thread2 holds a lock on obj2.
With in the synchronized method method1 there is a call to another synchronized method method2, both of the threads are trying to call method2 with the object whose lock is held by another object thus leading to a deadlock.

How to avoid deadlock in Java

With multi-threading programming deadlock may occur and there is no language support as such to prevent deadlocks. You will have to write your code used by multiple threads carefully to avoid deadlocks. Here we’ll go through the scenarios shown above and see how deadlocks can be avoided in those scenarios.

1– As shown in the previous scenarios one of the reason for the deadlock in Java is the way locks are acquired, if you have nested synchronization then you can acquire the object locks in the same order rather than in reverse order for both threads.

Changed nested synchronization code

Output

As you can see from the output now the deadlock is avoided.

2– Using synchronized block to minimize the synchronization to the critical section code only will also help in avoiding the deadlock in Java.

In the second scenario rather than synchronizing the whole method synchronized block can be used.

3– By using static synchronization in Java. If two object instances are used two threads using the two separate objects can still enter the synchronized method or block with their separate object locks. Static synchronization will help in this case because the lock will be acquired at the class level then.

How to debug a deadlock in Java

Detecting a deadlock in Java is not easy, even logs may be of little help. If you observe that your multi-threaded code is not performing as well as it was then it may be due to a deadlock and best thing is to get a thread dump of the application and analyze it.
You can use jstack utility to get a thread dump by providing the pid of the Java application. That pid can be obtained by running jps command.

As example – If I run the program where deadlock was created due to nested synchronization, then I can get the thread dump using following steps.

1– By using jps command I can get the pid of the Java application.

2– Run the jstack command with the pid as argument.

3– Get the thread dump and analyze it. Here some of the relevant portion of the thread dump is displayed.

That’s all for the topic Deadlock in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.