source:http://www.journaldev.com/1058/java-deadlock-example-and-how-to-analyze-deadlock-situation

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.

Java Deadlock Example

ThreadDeadlock.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.journaldev.threads;
 
public class ThreadDeadlock {
 
    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
     
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
         
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();
         
    }
 
}
 
class SyncThread implements Runnable{
    private Object obj1;
    private Object obj2;
 
    public SyncThread(Object o1, Object o2){
        this.obj1=o1;
        this.obj2=o2;
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " acquiring lock on "+obj1);
        synchronized (obj1) {
         System.out.println(name + " acquired lock on "+obj1);
         work();
         System.out.println(name + " acquiring lock on "+obj2);
         synchronized (obj2) {
            System.out.println(name + " acquired lock on "+obj2);
            work();
        }
         System.out.println(name + " released lock on "+obj2);
        }
        System.out.println(name + " released lock on "+obj1);
        System.out.println(name + " finished execution.");
    }
    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

In above program SyncThread is implementing Runnable interface and it works on two Objects by acquiring lock on each one of them one by one using synchronized block.

In main method, I have three threads running for SyncThread and there is a shared resource between each of the threads. The threads are run in such a way that it will be able to acquire lock on the first object but when it’s trying to acquire lock on second object, it goes on wait state because it’s already locked by another thread. This forms a cyclic dependency for resource between Threads causing deadlock.

When I execute the above program, here is the output generated but program never terminates because of deadlock.

1
2
3
4
5
6
7
8
9
t1 acquiring lock on java.lang.Object@6d9dd520
t1 acquired lock on java.lang.Object@6d9dd520
t2 acquiring lock on java.lang.Object@22aed3a5
t2 acquired lock on java.lang.Object@22aed3a5
t3 acquiring lock on java.lang.Object@218c2661
t3 acquired lock on java.lang.Object@218c2661
t1 acquiring lock on java.lang.Object@22aed3a5
t2 acquiring lock on java.lang.Object@218c2661
t3 acquiring lock on java.lang.Object@6d9dd520

Here we can clearly identify the deadlock situation from the output but in real life applications it’s very hard to find the deadlock situation and debug them.

Analyze Deadlock

To analyze a deadlock, we need to look at the java thread dump of the application, in last post I explained how we can generate thread dump using VisualVM profiler or using jstack utility.

Here is the thread dump of above program.

2012-12-27 19:08:34
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):
 
"Attach Listener" daemon prio=5 tid=0x00007fb0a2814000 nid=0x4007 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"DestroyJavaVM" prio=5 tid=0x00007fb0a2801000 nid=0x1703 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"t3" prio=5 tid=0x00007fb0a204b000 nid=0x4d07 waiting for monitor entry [0x000000015d971000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f658> (a java.lang.Object)
    - locked <0x000000013df2f678> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
 
"t2" prio=5 tid=0x00007fb0a1073000 nid=0x4207 waiting for monitor entry [0x000000015d209000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f678> (a java.lang.Object)
    - locked <0x000000013df2f668> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
 
"t1" prio=5 tid=0x00007fb0a1072000 nid=0x5503 waiting for monitor entry [0x000000015d86e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f668> (a java.lang.Object)
    - locked <0x000000013df2f658> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
 
"Service Thread" daemon prio=5 tid=0x00007fb0a1038000 nid=0x5303 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"C2 CompilerThread1" daemon prio=5 tid=0x00007fb0a1037000 nid=0x5203 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"C2 CompilerThread0" daemon prio=5 tid=0x00007fb0a1016000 nid=0x5103 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"Signal Dispatcher" daemon prio=5 tid=0x00007fb0a4003000 nid=0x5003 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
 
"Finalizer" daemon prio=5 tid=0x00007fb0a4800000 nid=0x3f03 in Object.wait() [0x000000015d0c0000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
    - locked <0x000000013de75798> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
 
"Reference Handler" daemon prio=5 tid=0x00007fb0a4002000 nid=0x3e03 in Object.wait() [0x000000015cfbd000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000013de75320> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:503)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
    - locked <0x000000013de75320> (a java.lang.ref.Reference$Lock)
 
"VM Thread" prio=5 tid=0x00007fb0a2049800 nid=0x3d03 runnable
 
"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb0a300d800 nid=0x3503 runnable
 
"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb0a2001800 nid=0x3603 runnable
 
"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb0a2003800 nid=0x3703 runnable
 
"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb0a2004000 nid=0x3803 runnable
 
"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb0a2005000 nid=0x3903 runnable
 
"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb0a2005800 nid=0x3a03 runnable
 
"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb0a2006000 nid=0x3b03 runnable
 
"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb0a2006800 nid=0x3c03 runnable
 
"VM Periodic Task Thread" prio=5 tid=0x00007fb0a1015000 nid=0x5403 waiting on condition
 
JNI global references: 114
 
 
Found one Java-level deadlock:
=============================
"t3":
  waiting to lock monitor 0x00007fb0a1074b08 (object 0x000000013df2f658, a java.lang.Object),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x00007fb0a1010f08 (object 0x000000013df2f668, a java.lang.Object),
  which is held by "t2"
"t2":
  waiting to lock monitor 0x00007fb0a1012360 (object 0x000000013df2f678, a java.lang.Object),
  which is held by "t3"
 
Java stack information for the threads listed above:
===================================================
"t3":
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f658> (a java.lang.Object)
    - locked <0x000000013df2f678> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
"t1":
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f668> (a java.lang.Object)
    - locked <0x000000013df2f658> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
"t2":
    at com.journaldev.threads.SyncThread.run(ThreadDeadlock.java:41)
    - waiting to lock <0x000000013df2f678> (a java.lang.Object)
    - locked <0x000000013df2f668> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:722)
 
Found 1 deadlock.

The thread dump output clearly shows the deadlock situation and threads and resources involved causing deadlock situation.

For analyzing deadlock, we need to look out for the threads with state as BLOCKED and then the resources it’s waiting to lock, every resource has a unique ID using which we can find which thread is already holding the lock on the object. For example Thread “t3” is waiting to lock 0x000000013df2f658 but it’s already locked by thread “t1”.

Once we analyze the deadlock situation and found out the threads which are causing deadlock, we need to make code changes to avoid deadlock situation.

Avoid deadlock

These are some of the guidelines using which we can avoid most of the deadlock situations.

  • Avoid Nested Locks: This is the most common reason for deadlocks, avoid locking another resource if you already hold one. It’s almost impossible to get deadlock situation if you are working with only one object lock. For example, here is the another implementation of run() method without nested lock and program runs successfully without deadlock situation.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " acquiring lock on " + obj2);
        synchronized (obj2) {
            System.out.println(name + " acquired lock on " + obj2);
            work();
        }
        System.out.println(name + " released lock on " + obj2);
     
        System.out.println(name + " finished execution.");
    }
  • Lock Only What is Required: You should acquire lock only on the resources you have to work on, for example in above program I am locking the complete Object resource but if we are only interested in one of it’s fields, then we should lock only that specific field not complete object.
  • Avoid waiting indefinitely: You can get deadlock if two threads are waiting for each other to finish indefinitely using thread join. If your thread has to wait for another thread to finish, it’s always best to use join with maximum time you want to wait for thread to finish.

If you liked this tutorial, make sure to check out other java thread tutorial.

Java Deadlock Example and How to analyze deadlock situation的更多相关文章

  1. Java核心技术点之多线程

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 本文主要从整体上介绍Java中的多线程技术, ...

  2. Java线程与多线程教程

    本文由 ImportNew - liken 翻译自 Journaldev.   Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...

  3. Java中的多线程技术全面详解

    本文主要从整体上介绍Java中的多线程技术,对于一些重要的基础概念会进行相对详细的介绍,若有叙述不清晰或是不正确的地方,希望大家指出,谢谢大家:) 为什么使用多线程 并发与并行 我们知道,在单核机器上 ...

  4. Deadlock Detecting--转

    /* Java Threads, 3rd Edition By Scott Oaks, Henry Wong 3rd Edition September 2004 ISBN: 0-596-00782- ...

  5. log4j deadlock

    用了这么久的Log4j这次倒下了,而且官方也还没有给出解决方案. 描述:tomcat 经过一天多时间的访问,出现了hang ,使用 Jstack 查看堆栈后,发现现成 blocked ,主要是 Log ...

  6. 14.3.5.1 An InnoDB Deadlock Example

    14.3.5 Deadlocks in InnoDB 14.3.5.1 An InnoDB Deadlock Example 14.3.5.2 Deadlock Detection and Rollb ...

  7. Troubleshooting &quot;Global Enqueue Services Deadlock detected&quot; (Doc ID 1443482.1)

    In this Document   _afrLoop=1021148011984950&id=1443482.1&displayIndex=1&_afrWindowMode= ...

  8. SQL Server technical bulletin - How to resolve a deadlock

    https://support.microsoft.com/en-us/help/832524/sql-server-technical-bulletin-how-to-resolve-a-deadl ...

  9. Java性能提示(全)

    http://www.onjava.com/pub/a/onjava/2001/05/30/optimization.htmlComparing the performance of LinkedLi ...

随机推荐

  1. kali linux2.0安装vega

    1.到官网下载安装包(选择版本:我这里以Linux64位为例) vega下载地址:https://subgraph.com/vega/download/ 2.解压到指定目录: unzip VegaBu ...

  2. python3 之__str__

    当某个类定义了__str__方法是,打印该类的实例对象就是打印__str__方法return出来的数据 示例: class Cat: """定义了一个Cat类" ...

  3. 《jquery实战》javascript 必知必会(1)

    A1 javascript对象的基本原理 JS 的 Object 与其他兄弟面向对象所定义的根本对象,几乎没有什么共同之处. JS 的 Object 一旦创建,它不持有任何数据,而且不表示什么语义. ...

  4. 一步一步学习IdentityServer3 (4)

    其实上述例子 很多都很找到 但是在实际生态环境中给例子有很多不一样的地方 比如自定已登录界面怎么做? 怎么访问自己的用户数据库实现登录? 怎么在接口中使用,在接口中又怎么实现与Idr3结合授权? 等等 ...

  5. C++ 矩阵库 eigen

    找了好久才发现了一个这么方便的C++矩阵库. 官网 http://eigen.tuxfamily.org/index.php?title=Main_Page 参考文章 http://blog.csdn ...

  6. 009.Zabbix幻灯片展示

    一 Slide shows简介 Slide shows在多个Screens之间以幻灯片的方式来展示,使一个屏幕可以显示多个页面. 二 Slide shows配置 2.1 创建多个Screen Slid ...

  7. 011.MySQL双主多从+Keepalived配置

    一 基础环境 主机名 系统版本 MySQL版本 主机IP Master01 CentOS 6.8 MySQL 5.6 172.24.8.10 Master02 CentOS 6.8 MySQL 5.6 ...

  8. Redis高可用之哨兵模式Sentinel配置与启动(五)

    0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...

  9. Redis指令与数据结构(二)

    0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...

  10. collectionFramwork-1

    1. Set.List和Map可以看做集合的三大类. List集合是有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问. Set集合是无序集合,集合中的元素不可以重复,访问集合中 ...