Java死锁检测以及解决办法
Java死锁检测以及解决办法
一、死锁概念
1. 什么是死锁?
两个或者多个线程互相持有对方所需要的资源, 都在等待对方执行完毕才能继续往下执行的时候,就称为发生了死锁。结果就是两个线程或多个线程都陷入了无限的等待中。由于线程被无限期地阻塞,因此程序不可能正常终止。
一般是有多个锁对象的情况下并且获得锁顺序不一致造成的。
2. java 死锁产生的四个必要条件
1) 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2)不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3)请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4)循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
3. 死锁的影响
1)系统资源浪费
一旦发生死锁,相关的进程会无限期地占用系统资源,而这些资源无法被其他进程使用,导致系统资源的浪费和利用率降低。
2)系统性能下降
死锁会导致进程长时间等待,影响系统响应时间,严重时甚至可能让系统无法响应新的请求,导致性能显著下降。
3)系统稳定性降低
死锁使得部分进程停滞,从而影响依赖这些进程的其他部分,甚至导致整个系统失去响应,影响系统的稳定性和可靠性。
4. 如何避免死锁?
为了避免死锁的危害,通常需要在设计阶段进行预防,包括资源分配有序化、锁定顺序控制、减少锁的粒度等策略,同时在运行时进行死锁检测和恢复。
二、死锁示例
代码示例如下:
1 public class DeadLock { 2 /** 3 * 创建两个对象,用两个线程分别先后独占 4 */ 5 private Boolean flag1 = true; 6 private Boolean flag2 = false; 7 8 public static void main(String[] args) { 9 DeadLock deadLock = new DeadLock(); 10 11 new Thread(new Runnable() { 12 @Override 13 public void run() { 14 System.out.println("线程1开始,作用是当flag1 = true 时,将flag2也改为 true"); 15 synchronized (deadLock.flag1){ 16 if(deadLock.flag1){ 17 try{ 18 //睡眠1s ,模拟业务执行耗时,并保证两个线程进入死锁状态 19 Thread.sleep(1000); 20 }catch (InterruptedException e){ 21 e.printStackTrace(); 22 } 23 System.out.println("flag1 = true,准备锁住flag2..."); 24 synchronized (deadLock.flag2){ 25 deadLock.flag2 = true; 26 } 27 } 28 } 29 } 30 }).start(); 31 32 new Thread(new Runnable() { 33 @Override 34 public void run() { 35 System.out.println("线程2开始,作用是当flag2 = false 时,将flag1也改为 false"); 36 synchronized (deadLock.flag2){ 37 if(!deadLock.flag2){ 38 try{ 39 //睡眠1s ,模拟业务执行耗时,并保证两个线程进入死锁状态 40 Thread.sleep(1000); 41 }catch (InterruptedException e){ 42 e.printStackTrace(); 43 } 44 System.out.println("flag2 = false,准备锁住flag1..."); 45 synchronized (deadLock.flag1){ 46 deadLock.flag1 = false; 47 } 48 49 } 50 } 51 } 52 }).start(); 53 } 54 }
三、死锁检测
1. jps
jps -l
查看所有的jvm进程,包括进程ID,进程启动的路径等等。
如下图:
2. jstack
jstack [pid]
jstack命令用于生成虚拟机当前时刻的线程快照。通过这个命令,可以观察jvm中当前所有线程的运行情况和线程当前状态。
执行命令:jstack 10928,截取部分运行结果,如下图:
3. 可视化工具 jconsole
从Java 5开始 引入了 JConsole,JConsole 是一个内置 Java 性能分析器。
主要用于基础的 JVM 监控,适合于查看应用程序的基本运行状况。它提供了一些基础指标,比如 CPU、内存使用率、线程状态、类加载信息以及基本的 MBeans 信息。它简单轻便,适合对应用进行基本的监控。
1)在命令终端输入:jconsole
2)点击连接进去
进入所检测的进程后,选择“线程”选项卡,并点击“检测死锁”。即可出来检测结果。如下图:
4. 可视化工具 visual VM
Visual VM 功能比 JConsole 更全面,除了 JConsole 提供的基础监控功能外,VisualVM 还支持更复杂的调试和性能分析。它可以进行 CPU 和内存的详细分析、线程分析、内存泄露检测,还可以生成堆转储文件、线程转储、GC 日志等,并支持通过插件扩展功能,比如集成 BTrace 进行动态追踪。
可以点击右上角Dump按钮,将线程的信息导出,其实就是执行的jstack命令
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2020-11-10 Mysql的联(复)合索引