Java死锁范例以及如何分析死锁

Java 程序死锁问题原理及解决方案(来源IBM开发者论坛本文作者文章) 本文首先介绍了死锁发生的原因,并通过一个示例解释了死锁发生的前提情况。然后通过 JVM 的 jstack 工具演示了如何确定一个死锁的发生。最后对死锁的预防、恢复等方式进行了解释。 原文地址:https://www.ibm.com/developerworks/cn/java/j-lo-deadlock/ 阅读详情

死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。

Java死锁范例

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();
         }
     }
}

在上面的程序中同步线程正完成Runnable的接口,它工作的是两个对象,这两个对象向对方寻求死锁而且都在使用同步阻塞。

在主函数中,我使用了三个为同步线程运行的线程,而且在其中每个线程中都有一个可共享的资源。

这些线程以向第一个对象获取封锁这种方式运行。但是当它试着像第二个对象获取封锁时,它就会进入等待状态,因为它已经被另一个线程封锁住了。这样,在线程引起死锁的过程中,就形成了一个依赖于资源的循环。

当我执行上面的程序时,就产生了输出,但是程序却因为死锁无法停止。

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

在此我们可以清楚地在输出结果中辨认出死锁局面,但是在我们实际生活所用的应用中,发现死锁并将它排除是非常难的。

分析死锁

为了分析一个死锁,我们需要关注下应用中的Java线程转存,在上一节中我已经解释了如何使用VisualVM收集资料或者jstack应用程序产生线程转存。

以下就是上述程序的线程转存。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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.

这三个线程转存的输出清楚地说明了死锁环境和线程,以及包含死锁环境的资源。

为了分析死锁,我们需要关注死锁状态的线程,然后资源再等待去封锁,每一个资源都有一个独特的ID,有了这个ID我们就能发现是哪一个进程已经封锁住对象。举个例子,线程“t3”正在等待封锁0x000000013df2f658,但是它已经被线程“t1”封锁住了。

当我们分析死锁环境的时候,如果发现线程正在引起死锁,这是我们就要改变代码来避免死锁的产生。

避免死锁

有很多方针可供我们使用来避免死锁的局面。

  • 避免嵌套封锁:这是死锁最主要的原因的,如果你已经有一个资源了就要避免封锁另一个资源。如果你运行时只有一个对象封锁,那是几乎不可能出现一个死锁局面的。例如,这里是另一个运行中没有嵌套封锁的run()方法,而且程序运行没有死锁局面,运行得很成功。
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." );
}
  • 只对有请求的进行封锁:你应当只想你要运行的资源获取封锁,比如在上述程序中我在封锁的完全的对象资源。但是如果我们只对它所属领域中的一个感兴趣,那我们应当封锁住那个特殊的领域而并非完全的对象。
  • 避免无限期的等待:如果两个线程正在等待对象结束,无限期的使用线程加入,如果你的线程必须要等待另一个线程的结束,若是等待进程的结束加入最好准备最长时间。
FPGA JTAG调试实战:从ID Code报错到硬件信号链排查 在数字电路调试中,JTAG(联合测试行动组)接口是连接软件与硬件的重要桥梁,它基于IEEE 1149.1标准,通过边界扫描链实现对芯片内部状态的访问与控制。其核心机制之一是JTAG ID Code——一个32位的芯片身份标识,由制造商在出厂时固化,用于验证器件型号与连接状态。当编程工具读取到的ID Code与预期值不匹配时,往往意味着信号链路的通信异常,这直接影响了FPGA的配置与调试效率。从工程实践角度看,此类问题通常源于硬件链路质量或软件配置失配,涉及电源完整性、信号时序、PCB焊接等底层因素。例如,电 阅读详情

相关推荐

蓝桥杯FPGA赛道积分赛

代码如下: 按键驱动 代码如下 按键驱动 代码如下: 顶层文件 按键驱动 数码管驱动 声明:本代码借鉴网络资料,如有侵权和错误请联系作者删除。我是从寒假开始备赛的,由于我基础不行,备赛过程中也是混混呃呃的,备赛效率不高,总体来说备赛不认真,有点拖拉,但是最后我也坚持备赛到了今天,在备赛过程中,即复习了旧的东西,也学到了新的东西,总结起来还是有点收获的,后天北京、天津、河北地区就要进行省赛了,我会全力以赴,不管结果怎么样,尽力就好,最后祝大家都能

weixin_69804913的博客 1984

面试之 Java 并发编程(三)

17、多线程同步和互斥有几种实现方法,都是什么 线程同步是指线程之间所具有的一种制约关系, 一个线程的执行依赖另一个线程的消息, 当它没有得到另一个线程的消息时应等待, 直到消息到达时才被唤醒。线程互斥是指对 于共享的进程系统资源, 在各单个线程访问时的排它性。当有若干个线程都要使用某一共 享资源时, 任何时刻最多只允许一个线程去使用, 其它要使用该资源的线程必须等待, 直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步。 线程间的同步方法大体可分为两类: 用户模式和内核模式。顾名思义, 内核

kfyong的专栏 223

在没有实验数据的情况下,如何高效快速发表高影响因子论文

最新基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法

glldxh的博客 371

Java死锁情况下打印日志_通过JVM日志分析排查Java线程死锁

通过JVM日志分析排查Java线程死锁两种办法:使用jstack 命令和jconsole工具1. jstack(1) 首先通过 jps 命令查看需要查看运行的Java进程列表,得到想查看的进程的id。(2)执行: jstack -l :得到一些log,可以看到获取,释放,等待锁等log情况2. 使用jconsole: 命令行直接jconsole打开jconsole,这是个可视化的工具,可以查看:概...

weixin_35992471的博客 996

换频道——假想《道德经》与量子力学的一些联系

之前看到一位AI PM的前辈分享了自己对于PM境界的看法: 境界一,行事被放心。 境界二,独立主导产品线从0到1,做正确的事,并把事做正确。 境界三,一切以灵魂境界为基础,产品作为其理念的衍生。 对于我,3个月尝试于目标而无获,但塞翁失马焉知非福。自己已经具备境界一,虽然境界二尚未成熟,但境界三却有幸有所思考。 今天,往澳门的动车途中有感而发,为随笔。

1020

win10删除vmware12后,重新安装失败(遗留注册表问题)解决总结

之前安装过一次VMware虚拟机,后来由于某些已遗忘原因把它卸载了,但是没有卸载完全,为以后安装留下了一些麻烦,现在根据我google很多内容总结后写下了自己的解决办法。 一些我搜的的可以用的VM12的注册码 5A02H-AU243-TZJ49-GTC7K-3C61N ZZ510-DYX47-48ERP-D6XZG-YCKU2 YV5MU-2FX5H-M841P-LZX5X-PYHX8

Jeason的博客 2万+

java死锁范例_Java死锁范例以及如何分析死锁

[java]代码库package com.journaldev.threads;public class ThreadDeadlock {public static void main(String[] args) throws InterruptedException {Object obj1 = new Object();Object obj2 = new Object();Object ob...

weixin_34672536的博客 85

基于 Cognex VisionPro 的工业级图像匹配技术全解析

通过本文的深度解析,开发者可以系统掌握 Cognex VisionPro 图像匹配技术的核心原理、开发流程、优化策略及工业级应用。实际项目中,需结合具体场景灵活调整参数,综合运用预处理、特征提取和匹配算法,构建稳定可靠的视觉系统。

品质生活,极致编程。 1594

java如何制造死锁_Java死锁范例以及如何分析死锁

死锁是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。在这里我已写好一个简单的程序,它将会引起死锁方案然后我们就会明白如何分析它。Java死锁范例ThreadDeadlock.java在上面的程序中同步线程正完成Runnable的接口,它工作的是两个对象,这两个对象向对方寻求死锁而且都在使用同步阻塞。在主函数中,我使用了三个为同步线程运行的线程,而且...

weixin_42121058的博客 162

四足狗机器人硬件开发技术栈详解

本文系统介绍了四足狗机器人的硬件开发技术,重点分析了五大核心模块:机械结构(骨架设计)、动力系统(关节驱动)、感知系统(环境监测)、控制系统(决策中枢)和电源系统(能源管理)。文章详细阐述了各模块的选型标准、技术要点和协同设计原则,提供了从需求定位到组装调试的完整开发流程,并针对常见问题给出解决方案。随着材料轻量化、模块标准化和AI集成化的发展趋势,四足机器人硬件将向更灵活、更智能的方向演进,为工业巡检、应急救援等场景提供更强大的移动平台支持。

start_up_go的博客 284

MIMIC数据库简介

一 、MIMIC简介 MIMIC(Medical Information Mart for Intensive Care),是一个大型的公开数据库。该数据库记录了2001年至2019年期间贝斯以色列女狄肯斯医疗中心重症监护病房患者的相关数据,拥有4万多名患者的医疗健康数据和记录。 MIMIC数据库记录了人口统计学信息,如病人的性别、身高、宗教等情况。记录了实验室检验信息,如血常规,肝功能,肾功能等实验室检测数据。记录了患者的用药信息,如高血压患者服用了治疗高血压类药物等。记录了护理人员以及患者的护理级别等。

越努力 越幸运 1万+

java死锁代码6_Java 死锁范例以及如何分析死锁

2012-12-27 19:08:34Full 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]j...

weixin_30880157的博客 551

泰山派rk3566 audio音频基础介绍

本文介绍了嵌入式系统中音频处理的基础知识,重点围绕RK3566平台的音频子系统展开。文章首先解释了音频信号从模拟到数字的转换过程,包括采样率、位深和声道等核心概念。随后详细分析了嵌入式音频开发中的关键接口:I2C用于控制音频编解码器,I2S作为专用音频数据传输总线,以及PCM作为原始音频格式和ALSA设备抽象的双重含义。通过对这些基础概念和接口的解析,为在RK3566平台上进行音频驱动开发和应用调试提供了理论基础。

qq_37077309的博客 294

Java死锁范例与死锁分析

死锁范例 下面是一个简单的死锁范例: package com.wlyuan.DeadLock; /** * Created by wlyuan on 17-4-4. */ public class ThreadDeadLock { public static void main(String[] args) { Object lock1 = new Object(

aitumingmumu的专栏 1013

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【JAVA 并发】三 死锁范例与分析

避免 死锁的方法就是不要写 顺序不一致加锁 的代码 如果 必须要写顺序不一致的加锁的代码,可以采用 trylock 方法,避免程序一直等待。 预防 死锁可以采用finddebug插件去扫描代码发现死锁。 处理 死锁,如果运行中的程序已经发生死锁,据我所知没有别的办法,只能停止程序,代价非常大,所以要尽量避免死锁。

maguochao_Mark的博客 363

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

死锁实现与问题定位

死锁范例: package com.array7.concurrent; public class DeadLockTest { private static Object res1 = new Object(); private static Object res2 = new Object(); public static void main(String[] arg...

weixin_30559481的博客 115

Java 线程死锁及如何避免死锁介绍

死锁是指两个或两个以上的线程在执行过程中,**因争夺资源而造成的互相等待**的现象,在无外力作用的情况下,这些线程会一直相互等待而无法继续运行下去,

weixin_46448719的博客 4824

Java线程之如何分析死锁及避免死锁

什么是死锁 java中的死锁是一种编程情况,其中两个或多个线程被永久阻塞,Java死锁情况出现至少两个线程和两个或更多资源。 在这里,我们将写了一个简单的程序,它将导致java死锁场景,然后我们将分析它。 怎么实现死锁 下面我们一起看一个简单的死锁事例,在主线程中每隔5秒钟启动一个线程,每个线程的执行时间是3秒钟 package com.lkf.mulithread; ...

码客 1万+

Java死锁示例–如何分析死锁情况

死锁是两个或多个线程永远被阻塞的编程情况,这种情况发生在至少两个线程和两个或更多资源的情况下。 在这里,我编写了一个简单的程序,该程序将导致出现死锁情况,然后我们将看到如何对其进行分析。 Java死锁示例 package com.journaldev.threads; public class ThreadDeadlock { public static void main(Str...

最佳 Java 编程 879

java 分析java死锁_Java死锁示例–如何分析死锁情况

java 分析java死锁 死锁是两个线程或多个线程永远被阻塞的编程情况,这种情况发生在至少两个线程和两个或更多资源的情况下。 在这里,我编写了一个简单的程序,它将导致死锁情况,然后我们将看到如何对其进行分析。 Java死锁示例 package com.journaldev.threads; public class ThreadDeadlock { public static vo...

最佳 Java 编程 326
上一篇: 代理模式
下一篇: Redis、Memcached、Guava、Ehcache中的算法
network_boy
博客等级 码龄12年 9粉丝 26原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值