简介:如果我们在程序中遇到线程死锁的时候,该怎么去解决呢? 本文将会从一个实际的例子出发,一步一步的揭开java问题解决的面纱。

简介

如果我们在程序中遇到线程死锁的时候,该怎么去解决呢?

本文将会从一个实际的例子出发,一步一步的揭开java问题解决的面纱。

死锁的代码

写过java多线程程序的人应该都知道,多线程中一个很重要的事情就是状态的同步,但是在状态同步的过程中,一不小心就有可能会导致死锁的问题。

一个最简单的死锁情况就是thread1占有资源1,然后又要去获取资源2. 而thread2占有资源2,又要去获取资源1的情况。

举个具体的例子:

public class TestDeadLock {public static Object lock1= new Object();public static Object lock2= new Object();public static void main(String[] args) {Runnable runnable1= ()-> {System.out.println("in lock1");synchronized(lock1){System.out.println("Lock1 lock obj1");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}synchronized(lock2){System.out.println("Lock1 lock obj2");}}};Runnable runnable2= ()-> {System.out.println("in lock2");synchronized(lock2){System.out.println("Lock2 lock obj2");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}synchronized(lock1){System.out.println("Lock2 lock obj1");}}};Thread a = new Thread(runnable1);Thread b = new Thread(runnable2);a.start();b.start();}
}

我们运行上面的代码:

in lock1
Lock1 lock obj1
in lock2
Lock2 lock obj2

发送了锁循环等待的情况,程序执行不下去了,发送了死锁。

control+break命令

在代码很简单的情况下,我们很容易就能分析出来死锁的原因,但是如果是在一个非常庞大的线上项目的时候,分析代码就没有那么容易了。

怎么做呢?

今天教给大家一个方法,使用control+break命令。

control+break在linux表示的是Control+backslash,而在Windows下面就是Control+Break按钮。

当然,还有一个更加通用的就是使用:

kill -QUIT pid命令。

我们用jps命令获取到执行java程序的进程id,然后执行kill -QUIT命令。

执行完毕,我们会发现运行的java进程会输出一些额外的日志,这些额外的日志就是我们找出死锁的关键因素。

注意,这个kill命令并不会终止程序的运行。

输出的内容比较多,我们一部分一部分的讲解。

Full thread dump

日志的第一部分就是Full thread dump,包含了JVM中的所有线程的状态信息。

我们看一下我们代码中的两个关键线程信息:

"Thread-0" #13 prio=5 os_prio=31 cpu=4.86ms elapsed=230.16s tid=0x00007fc926061800 nid=0x6403 waiting for monitor entry  [0x0000700008d6a000]java.lang.Thread.State: BLOCKED (on object monitor)at com.flydean.TestDeadLock.lambda$main$0(TestDeadLock.java:21)- waiting to lock <0x0000000787e868f0> (a java.lang.Object)- locked <0x0000000787e868e0> (a java.lang.Object)at com.flydean.TestDeadLock$$Lambda$14/0x0000000800b69840.run(Unknown Source)at java.lang.Thread.run(java.base@14.0.1/Thread.java:832)"Thread-1" #14 prio=5 os_prio=31 cpu=4.32ms elapsed=230.16s tid=0x00007fc924869800 nid=0x6603 waiting for monitor entry  [0x0000700008e6d000]java.lang.Thread.State: BLOCKED (on object monitor)at com.flydean.TestDeadLock.lambda$main$1(TestDeadLock.java:36)- waiting to lock <0x0000000787e868e0> (a java.lang.Object)- locked <0x0000000787e868f0> (a java.lang.Object)at com.flydean.TestDeadLock$$Lambda$15/0x0000000800b69c40.run(Unknown Source)at java.lang.Thread.run(java.base@14.0.1/Thread.java:832)

上面的输出列出了线程名字,线程的优先级,cpu时间,是否是daemon线程,线程ID,线程状态等有用的信息。

看到上面的输出,我们看到两个线程都是处于BLOCKED状态,都在等待object monitor。

还记得线程的几个状态吗? 我们再来复习一下。

死锁检测

接下来的部分就是我们最关心的死锁检测了。

Found one Java-level deadlock:
=============================
"Thread-0":waiting to lock monitor 0x00007fc926807e00 (object 0x0000000787e868f0, a java.lang.Object),which is held by "Thread-1""Thread-1":waiting to lock monitor 0x00007fc926807f00 (object 0x0000000787e868e0, a java.lang.Object),which is held by "Thread-0"Java stack information for the threads listed above:
===================================================
"Thread-0":at com.flydean.TestDeadLock.lambda$main$0(TestDeadLock.java:21)- waiting to lock <0x0000000787e868f0> (a java.lang.Object)- locked <0x0000000787e868e0> (a java.lang.Object)at com.flydean.TestDeadLock$$Lambda$14/0x0000000800b69840.run(Unknown Source)at java.lang.Thread.run(java.base@14.0.1/Thread.java:832)
"Thread-1":at com.flydean.TestDeadLock.lambda$main$1(TestDeadLock.java:36)- waiting to lock <0x0000000787e868e0> (a java.lang.Object)- locked <0x0000000787e868f0> (a java.lang.Object)at com.flydean.TestDeadLock$$Lambda$15/0x0000000800b69c40.run(Unknown Source)at java.lang.Thread.run(java.base@14.0.1/Thread.java:832)Found 1 deadlock.

上面的日志我们可以很明显的看出来,两个线程分别获得了对方需要的锁,所以导致了死锁。

同时还详细的列出了thread stack的信息,供我们分析。

如果我们添加了参数-XX:+PrintConcurrentLocks,还会输出各个线程的获得的concurrent lock信息。

Heap信息

最后一部分是Heap的统计信息:

Heapgarbage-first heap   total 133120K, used 3888K [0x0000000780000000, 0x0000000800000000)region size 1024K, 4 young (4096K), 0 survivors (0K)Metaspace       used 1122K, capacity 4569K, committed 4864K, reserved 1056768Kclass space    used 108K, capacity 412K, committed 512K, reserved 1048576K

如果我们添加了-XX:+PrintClassHistogram命令,还可以额外的输出class直方图统计信息。

总结

上面就是使用Control+Break命令来分析java死锁问题的具体例子,希望大家能够喜欢。

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/jvm-diagnostic-control-break/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

原文链接:https://developer.aliyun.com/article/769880?

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

troubleshoot之:用control+break解决线程死锁问题相关推荐

  1. java解决线程死锁_为你解决Java线程死锁

    产生死锁的原因: 1. 系统资源不足.分配不当.系统中都会有一种不可剥夺的资源,若是这些资源不能够满足进程运行的需要,那么就只能进行资源争夺,从而陷入死锁. 注意:只有对不可剥夺资源的竞争才可能产生死 ...

  2. Android/Linux线程死锁demo分析

    1.线程死锁 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <un ...

  3. java 多线程跑数据_java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁...

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 packagethread_test;public class ThreadDemo1 extendsTh ...

  4. unix线程死锁概念与解决

    线程死锁的两种方式 死锁概念:线程死锁指的是线程需要使用的公共资源一直被其他线程占用,导致该线程一直处于阻塞状态,无法继续执行. 那么造成死锁的情况主要有以下两种情况. 1.线程上锁,执行完具体逻辑之 ...

  5. 多线程编程:线程死锁的原因以及解决方法

    多线程编程:线程死锁的原因以及解决方法 关于线程死锁这个问题相信程序员在编写多线程程序时会经常遇到的一个经典问题,这种情况往往出现在多个线程同时对临界资源访问时所产生的. 属于临界资源的硬件有打印机. ...

  6. java中线程死锁的解决方法_Java线程死锁实例及解决方法

    这篇文章主要介绍了Java线程死锁实例及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.死锁的定义 所谓死锁是指多个线程因竞争资源而造成 ...

  7. 什么是线程死锁?如何解决?(蚂蚁金服面试题)

    认识线程死锁 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想 ...

  8. Log4j线程死锁–案例研究

    此案例研究描述了影响Weblogic Portal 10.0生产环境的Apache Log4j线程争用问题的完整根本原因分析和解决方案. 它还将说明在开发和支持Java EE应用程序时适当的Java类 ...

  9. JDK中ThreadDump诊断Java代码中的线程死锁问题

    多线程的死锁..死锁不是死了而是线程互相等待... 在项目中可能就是在几十万行的代码中存在一个死锁的问题,如何发现这个问题并且解决这个问题. JavaJDK为我们提供了一个诊断工具叫做ThreadDu ...

最新文章

  1. 工业计算机断层扫描原理,工业计算机断层扫描(CT).doc
  2. 并发基础(三): java线程优先级小试牛刀
  3. CVPR2019 | 目标检测新文:Generalized Intersection over Union
  4. 【.net 深呼吸】自定义应用程序配置节
  5. 以外的文件 删除_原来C盘还可以删除这五个文件,难怪电脑越来越卡!
  6. 122 - Trees on the level(模拟内存池解法)
  7. python连接db2数据库 import的包_python 连接DB2数据库
  8. solidity之call相关函数
  9. 一步一步学Ruby(五): Class, Module, Object,Kernel的关系
  10. 20171018校内训练
  11. mac更新完后读取不出移动硬盘的问题解决
  12. mkvtoolnix视频转换 v51.0.0中文版
  13. 电子签章服务器位置的确定,一文看懂如何实现服务端电子签章
  14. summernote富文本编辑器基本使用
  15. 百度地图坐标转高德地图坐标
  16. VM16Pro安装win7
  17. 为什么编程入门很多人都会推荐Java?
  18. Python爬虫Scrapy轮子工具
  19. Spring框架之AOP详解(带实战详细步骤)
  20. VHDL语言Process

热门文章

  1. 微软:明明修复了Bug,你们还把我骂上热搜?
  2. python显示range_python中range如何输出
  3. obj模型转json模型_微软文字转图像技术又进化,提出两种 GAN 的升级模型 | CVPR 2019...
  4. 完全背包问题从简单到复杂
  5. 如何成为一个伟大的 JavaScript 程序员
  6. 阅读之web应用安全
  7. python 不同模块之间的引用错误问题
  8. 一、Django前后端交互之Ajax和跨域问题
  9. 杭电oj2043密码
  10. Django中自定义过滤器的使用