Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >死锁分析以及检测工具详解

死锁分析以及检测工具详解

作者头像
JAVA葵花宝典
发布于 2020-02-20 10:07:44
发布于 2020-02-20 10:07:44
80800
代码可运行
举报
文章被收录于专栏:JAVA葵花宝典JAVA葵花宝典
运行总次数:0
代码可运行

锁的状态

死锁:线程1等待线程2的互斥持有资源,而线程2等着线程1的互斥持有资源,两个线程都无法进行执行。

活锁:线程持续重试一个总是失败的操作,导致无法继续执行。(不是本文的重点)

饿死:线程一直被调度器延迟访问其赖以执行的资源,也许是调度器先于低优先级的线程而执行高优先级的线程,同时总是会有一个高优先级的线程可以执行,饿死也叫做无限延迟。

死锁的案例

代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.karl.concurrent.deadlock;

/**
 * 描述:  死锁的场景
 *
 * @author mh
 * @create 2020-02-11 15:43
 */
public class DeadLockTest {
    private Object object1 = new Object();
    private Object object2 = new Object();

    public static void main(String[] args) {
        DeadLockTest deadLockTest = new DeadLockTest();

        Runnable runnable1 = () -> {
            while (true) {
                deadLockTest.method01();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {

                }
            }
        };

        Thread thread01 = new Thread(runnable1, "thread01");

        Runnable runnable2 = () -> {
            while (true) {
                deadLockTest.method02();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {

                }
            }
        };
        Thread thread02 = new Thread(runnable2, "thread02");


        thread01.start();
        thread02.start();
    }


    public void method01() {
        synchronized (object1) {
            synchronized (object2) {
                System.out.println("method01 invoked");
            }

        }
    }


    public void method02() {
        synchronized (object2) {
            synchronized (object1) {
                System.out.println("method02 invoked");
            }
        }
    }

}

控制台:

根据图中我们可以看出,程序在运行中,但一直没有任何输出。

图解:

死锁的检测工具

java VisualVM

打开方式:jvisualvm命令即可

界面:

双击本地下的我们刚才执行的程序DeadLockTest,的到如下页面:

我们选择Dump线程

如图可知:

  • 线程01 02 在阻塞状态
  • 都在等待获取monitor持有权
  • 线程01 等待锁0x000000076ada8128,而且已经锁定了0x000000076ada8138。
  • 线程02 等待0x000000076ada8138,而且已经锁定了0x000000076ada8128。刚好和线程01 是相反的。

具体的细节大家可以在本地演示一下。

通过命令行工具检测死锁

jps -l 找到我们的程序id

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
95007 com.karl.concurrent.deadlock.DeadLockTest

jstack 95007 查看线程情况

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2020-02-11 18:15:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):

"Attach Listener" #14 daemon prio=9 os_prio=31 tid=0x00007ffe9308c000 nid=0xa603 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007ffe940a6800 nid=0xe03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"thread02" #12 prio=5 os_prio=31 tid=0x00007ffe940a5800 nid=0xa703 waiting for monitor entry [0x0000700002706000]
   java.lang.Thread.State: BLOCKED (on object monitor)
  at com.karl.concurrent.deadlock.DeadLockTest.method02(DeadLockTest.java:60)
  - waiting to lock <0x000000076aeefc20> (a java.lang.Object)
  - locked <0x000000076aeefc30> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$2/381259350.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

"thread01" #11 prio=5 os_prio=31 tid=0x00007ffe940a5000 nid=0xa903 waiting for monitor entry [0x0000700002603000]
   java.lang.Thread.State: BLOCKED (on object monitor)
  at com.karl.concurrent.deadlock.DeadLockTest.method01(DeadLockTest.java:50)
  - waiting to lock <0x000000076aeefc30> (a java.lang.Object)
  - locked <0x000000076aeefc20> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$0(DeadLockTest.java:18)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$1/1607521710.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007ffe94049000 nid=0x3e03 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007ffe95875000 nid=0x4003 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007ffe93053800 nid=0x3c03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007ffe93053000 nid=0x3b03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007ffe93052000 nid=0x3a03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007ffe93050800 nid=0x3803 runnable [0x0000700001eee000]
   java.lang.Thread.State: RUNNABLE
  at java.net.SocketInputStream.socketRead0(Native Method)
  at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
  at java.net.SocketInputStream.read(SocketInputStream.java:171)
  at java.net.SocketInputStream.read(SocketInputStream.java:141)
  at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
  at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
  at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
  - locked <0x000000076ac83770> (a java.io.InputStreamReader)
  at java.io.InputStreamReader.read(InputStreamReader.java:184)
  at java.io.BufferedReader.fill(BufferedReader.java:161)
  at java.io.BufferedReader.readLine(BufferedReader.java:324)
  - locked <0x000000076ac83770> (a java.io.InputStreamReader)
  at java.io.BufferedReader.readLine(BufferedReader.java:389)
  at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007ffe9301d800 nid=0x3703 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007ffe9282a000 nid=0x4c03 in Object.wait() [0x0000700001be2000]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000076ab08ed0> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
  - locked <0x000000076ab08ed0> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007ffe9300f800 nid=0x4d03 in Object.wait() [0x0000700001adf000]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000076ab06bf8> (a java.lang.ref.Reference$Lock)
  at java.lang.Object.wait(Object.java:502)
  at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
  - locked <0x000000076ab06bf8> (a java.lang.ref.Reference$Lock)
  at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=31 tid=0x00007ffe9581c000 nid=0x4e03 runnable

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007ffe92806000 nid=0x1d07 runnable

"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007ffe92807000 nid=0x1f03 runnable

"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007ffe92807800 nid=0x2203 runnable

"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007ffe9280b000 nid=0x2a03 runnable

"GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007ffe9280b800 nid=0x2b03 runnable

"GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007ffe9280c800 nid=0x5303 runnable

"GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007ffe9280d000 nid=0x5103 runnable

"GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007ffe9280d800 nid=0x2d03 runnable

"VM Periodic Task Thread" os_prio=31 tid=0x00007ffe9400a000 nid=0x5503 waiting on condition

JNI global references: 319


Found one Java-level deadlock:
=============================
"thread02":
  waiting to lock monitor 0x00007ffe92826cb8 (object 0x000000076aeefc20, a java.lang.Object),
  which is held by "thread01"
"thread01":
  waiting to lock monitor 0x00007ffe928282b8 (object 0x000000076aeefc30, a java.lang.Object),
  which is held by "thread02"

Java stack information for the threads listed above:
===================================================
"thread02":
  at com.karl.concurrent.deadlock.DeadLockTest.method02(DeadLockTest.java:60)
  - waiting to lock <0x000000076aeefc20> (a java.lang.Object)
  - locked <0x000000076aeefc30> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$2/381259350.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)
"thread01":
  at com.karl.concurrent.deadlock.DeadLockTest.method01(DeadLockTest.java:50)
  - waiting to lock <0x000000076aeefc30> (a java.lang.Object)
  - locked <0x000000076aeefc20> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$0(DeadLockTest.java:18)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$1/1607521710.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

也能查看到死锁的状况

总结

生产环境死锁的检测,通常都是通过命令行的方式进行查看。

作者:小鱼儿-karl

原文链接:https://blog.csdn.net/qq_33249725/article/details/104267428

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA葵花宝典 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
15个多线程相关的面试题
场景描述:Java并发编程问题是面试过程中很容易遇到的问题,提前准备是解决问题的最好办法,将试题总结起来,时常查看会有奇效。
王知无-import_bigdata
2019/12/30
8130
虚拟机性能监控、故障处理关于控制台的命令整理
监视虚拟机各种运行状态信息;显示进程中的 类加载、内存、垃圾收集、即时编译 等; 如果没有GUI图形化界面的服务器,可以通过该命令查看运行状况,命令格式:
eeaters
2021/12/12
5760
虚拟机性能监控、故障处理关于控制台的命令整理
JVM之jstack实战死锁问题
如果在生产环境发生了死锁,我们将看到的是部署的程序没有任何反应了,这个时候我们可以借助 jstack进行分析,下面我们实战操作查找死锁的原因。所谓死锁指的是是一组互相竞争资源的线程因互相等待导致“永久”阻塞的现象。
共饮一杯无
2022/11/28
8150
JVM之jstack实战死锁问题
高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析
3. 紧接着,P1又抢到了锁,但是生产后没有被消费,所以直接进入LOCK.wati. 执行完以后释放锁。P1-----WAITING . 对应日志
小小工匠
2021/08/17
3520
一文搞定Java并发编程面试考点
任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。
Bug开发工程师
2019/05/04
3730
高并发之——线程与多线程
在操作系统中,线程是比进程更小的能够独立运行的基本单位。同时,它也是CPU调度的基本单位。线程本身基本上不拥有系统资源,只是拥有一些在运行时需要用到的系统资源,例如程序计数器,寄存器和栈等。一个进程中的所有线程可以共享进程中的所有资源。
冰河
2020/10/29
4110
高并发之——线程与多线程
JVM故障分析及性能优化实战(II)——jstack生成的Thread Dump日志结构解析
上一篇文章讲述了如何使用jstack生成日志文件,这篇文章首先对Thread Dump日志文件的结构进行分析。
IT技术小咖
2019/09/26
2.5K0
JVM故障分析及性能优化实战(II)——jstack生成的Thread Dump日志结构解析
2022年Java秋招面试,程序员求职必看的Java并发编程面试题
为一名专业的 Java 开发者,如何在并发场景中写出优良的代码,是一道绕不开的坎,也是考量一个 Java 开发者功底的关键技术。因此,不难发现 Java 并发问题一直是各个大厂面试的重点之一,然而我发现很多候选人在面试时,常常表示对各种并发原理一脸懵逼,好像知道一些却又讲不清楚,最终导致面试失败。于是发奋学习,啃大部头书又发现理论太多,头疼。其实 Java 的并发问题虽然内容繁杂,然而整个脉络还是很清晰的。
Java程序猿
2022/07/02
6010
不可不知的7个JDK命令
武培轩(公众号:武培轩)的《不可不知的7个JDK命令》这篇文章,短小精悍,介绍的这7个JDK命令非常实用,值得借鉴。
bisal
2020/05/18
4310
不可不知的7个JDK命令
并发编程原理剖析——多线程及其原理分析 顶
客户端阻塞:如果客户端只有一个线程,这个线程发起读取文件的额操作必须等待IO流返回,客户端才能做其它事情。
须臾之余
2019/07/09
7400
Java自带的性能监测工具之jstack
本文继续介绍Java自带的性能监测工具,本文使用jstack (Java Stack Trace)工具来玩~
孟君
2023/02/23
2.7K0
Java自带的性能监测工具之jstack
JAVA Thread Dump 文件分析
Thread Dump是非常有用的诊断Java应用问题的工具。每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-dump的能力,虽然各个 Java虚拟机打印的thread dump略有不同,但是大多都提供了每个线程的所有信息,例如: 线程状态、线程 Id、本机 Id、线程名称、堆栈跟踪、优先级。
Java宝典
2021/01/15
1.3K0
Java 并发编程中的死锁 ( Kotlin 语言讲解)
在操作系统中的并发处理场景中, 进程对资源的持有与请求过程中,会产生死锁. Say, Process A has resource R1 , Process B has resource R2. If Process A request resource R2 and Process B requests resource R1, at the same time , then deadlock occurs.
一个会写诗的程序员
2019/07/08
1.3K0
Java 并发编程中的死锁 ( Kotlin 语言讲解)
JVM 基础知识
JVM 是可运行 Java 中假想的计算机,就是在真实的计算机上模拟计算机功能,包括一套字节指令,一套寄存器,一个栈,一个垃圾回收,堆,一个存储区域,JVM 是运行在操作系统之上,它与硬件没有直接的交互。
王小明_HIT
2020/02/17
5540
JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)
JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps、jstack、jmap、jhat、jstat、hprof等小巧的工具,每一种工具都有其自身的特点,用户可以根据你需要检测的应用或者程序片段的状况,适当的选择相应的工具进行检测。接下来的两个专题分别会讲VisualVM的具体应用。
java干货
2021/02/19
6910
JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)
jvm调优
查看java程序运行的环境参数,包括Java System属性和JVM命令行参数.。
IT云清
2019/06/14
1K0
jvm调优
jstack查看某个进程堆栈信息
jstack主要用来查看某个进程内线程的堆栈信息 一个死锁的模拟代码 package test; import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** * @className: test * @description: TODO 类描述 * @author: mac * @date: 2020/12/3 **/ public class test { public static
开源日记
2020/12/10
3.3K0
JDK 1.8 的 HashMap 详解: 为什么并发会出问题?甚至出现死循环导致系统不可用?
为什么说HashMap是非线程安全的呢?因为在高并发情况下,HashMap在一些操作上会存在问题,如死循环问题,导致CPU使用率较高。
一个会写诗的程序员
2020/02/25
4.7K0
JDK 1.8 的 HashMap 详解: 为什么并发会出问题?甚至出现死循环导致系统不可用?
源码分析:Java中的Thread的创建和运行
在面试候选人的时候,我有时候会提出这样的一个问题:说说你对Java线程的理解?从这个问题开始,可以考察候选人对并发基础的掌握、对操作系统基本概念的理解,如果遇到对底层有浓厚兴趣的同学,我会抛出另一个问题:Java里的线程和操作系统的线程是什么关系?它们是如何对应的?这两个问题,就是今天这篇文章想讲述的。
阿杜
2018/12/27
1.3K0
性能优化-jstack的使用
有些时候我们需要查看下jvm中的线程执行情况,比如,发现服务器的CPU的负载突然增高了、出现了死锁、死循环等,我们该如何分析呢?
cwl_java
2020/02/13
2.2K0
推荐阅读
相关推荐
15个多线程相关的面试题
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验