1 缘起

在学习ArrayBlockingQueue(ABQ)的过程中,
实现队列阻塞相关的功能是通过java.util.concurrent.locks.Condition,
如enqueue的notEmpty和dequeue的notFull均是Condition,
通过await实现等待,这里我由此想到了中断线程的知识,
通过翻阅java.lang.Thread源码发现,Thread.stop、Thread.suspend和Thread.resume均被JDK1.8标记为Deprecated,
源码中给出了说明文档:https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html,
说是多线程间不安全,可能形成死锁,
于是,我就自己通过代码实现了一下死锁,
同时,结合示意图以及时间序列图分析讲解死锁,
并给出了死锁分析工具jconsole的是使用案例,
检测运行的Java服务中是否有死锁,以及出现死锁的线程,
帮助读者轻松应对知识考核与交流。

2 死锁

多个线程间相互申请锁住对方尚未释放的资源,如对象,方法等,
线程间依赖等待对方释放资源,造成的死循环。
死锁图例如下图所示,
图中展示了线程T1和线程T2分别申请对象A和对象B而造成的死锁,
初始化阶段,线程T1有对象A,线程T2持有对象B,
死锁阶段,线程T1在线程T2持有对象B的阶段申请锁住对象B,
线程T2在线程T1持有对象A的阶段申请锁住对象A,
由于线程在各自占有资源的情况下,相互申请对方持有的资源,
双方都不会退出资源申请,形成环形等待,即死锁。

2.1 Code

package com.monkey.java_study.lock;import com.monkey.java_study.common.entity.UserEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 死锁测试.** @author xindaqi* @since 2022-10-08 10:59*/
public class DeadLockTest {private static final Logger logger = LoggerFactory.getLogger(DeadLockTest.class);public static void main(String[] args) {UserEntity u1 = new UserEntity("0x001");UserEntity u2 = new UserEntity("0x002");Thread t1 = new Thread(() -> {synchronized (u1) {logger.info(">>>>>>>>>>T1 start");try {logger.info(">>>>>>>>>>U1:{}", u1);synchronized (u2) {u2.setNickname("u2-edit");logger.info(">>>>>>>>>>U2:{}", u2);}Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});Thread t2 = new Thread(() -> {synchronized (u2) {logger.info(">>>>>>>>>>T2 start");try {Thread.sleep(2000);logger.info(">>>>>>>>>>U2:{}", u2);synchronized (u1) {u1.setNickname("u1-edit");logger.info(">>>>>>>>>>U1:{}", u1);}} catch (InterruptedException e) {throw new RuntimeException(e);}}});t1.start();t2.start();}
}

2.2 结果

3 死锁分析

3.1 时序图解

下面以时序分解的方式分析死锁,过程如下图所示。
约定:线程T1,线程T2,对象A,对象B
线程T1占有对象A的时间段:[t1, t1+4]
线程T2占有对象B的时间段:[t1+1, t1+4]
线程T1在t1+2时刻申请对象B,此时对象B仍被线程T2持有,线程T1若想申请并锁住对象B,需要等到线程T2释放对象B,
线程T2在t1+3时刻申请对象A,此时对象A仍被线程T1持有,线程T2若想申请并锁住对象A,需要等到线程T1释放对象A,
然而在线程各自占有资源期间,申请了对方尚未释放的资源,相互等待,形成等待环,即死锁。

3.2 jconsole排查死锁

3.2.1 打开jconsole

jconsole是JDK(1.8)自带的工具,安装JDK后可直接使用,控制台输入jconsole即可调用jconsole客户端,
图形界面如下图所示。
由图可知,jconsole监控了运行的Java进程,既可以连接本地Java进行,又可以连接远程的Java进程,
这里选择DeadLockTest测试死锁的Java进程,并连接。

3.2.2 连接Java进程

本地Java进程没有配置SSL安全连接,因此jconsole连接时会提示非安全连接,
如下图所示,这里选择不安全的连接,连接DeadLockTest进程。

3.2.3 线程

进入监控页面后,选择线程属性,如下图所示,
下方有检测死锁的按钮,点击即可检测当前Java进程中的死锁。

3.2.4 死锁

检测死锁后,发现该DeadLockTest进程中存在死锁线程,
如下图所示,发生死锁的线程为Thread-1和Thread-2。
初始化:
线程Thread-1持有对象A(UserEntity@27b4a46d)
线程Thread-2持有对象B(UserEntity@37a0d490)

  • Thread-2信息
    对于线程Thread-2,如下图所示,
    由状态可知:申请并锁定对象A(UserEntity@27b4a46d)时,
    该对象被线程Thread-1持有;
    由堆栈跟踪可知:线程Thread-2锁定对象B(UserEntity@37a0d490),
    由总阻止数可知:由于申请的资源被其他线程占有,因此,阻止获取对象A(UserEntity@27b4a46d)。
  • Thread-1信息
    对于线程Thread-1,如下图所示,
    由状态可知:申请并锁定对象B(UserEntity@37a0d490)时,
    该对象被线程Thread-2持有;
    由堆栈跟踪可知:线程Thread-1锁定对象A(UserEntity@27b4a46d),
    由总阻止数可知:由于申请的资源被其他线程占有,因此,阻止获取对象B(UserEntity@37a0d490)。

4 小结

(1)死锁:多个线程间相互申请锁住对方尚未释放的资源,如对象,方法等,线程间依赖等待对方释放资源,造成的死循环。
(2)Thread以标记弃用:Thread.suspend、Thread.resume和Thread.stop,因会造成死锁;
(3)Thread停止推荐使用Thread.interrupt。

实践讲解死锁及死锁检测(图+文+代码)相关推荐

  1. 【项目实践】U-V视差路面检测之动态规划

    系列文章: 双目视觉(一)双目视觉系统 双目视觉(二)双目匹配的困难和评判标准 双目视觉(三)立体匹配算法 双目视觉(四)匹配代价 双目视觉(五)立体匹配算法之动态规划全局匹配 双目视觉(六)U-V视 ...

  2. 死锁-死锁预防、死锁避免(资源分配图与银行家算法)、死锁检测、死锁解除

    文章目录 1 死锁 2 死锁预防 3 死锁避免 4 死锁检测 5 死锁解除 6 参考文献 1 死锁 什么是死锁     通俗的讲,就是两个或多个进程无限期的阻塞.相互等待的一种状态.比如哲学家进餐问题 ...

  3. java线程死锁 cpu 100%_一文学会Java死锁和CPU 100% 问题的排查技巧

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开 工欲善其事,必先利其器 00 本文简介 作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在 ...

  4. 2.5操作系统(预防死锁 避免死锁 检测和解除死锁)

    目录 1.死锁 1.什么是死锁? 2.死锁.饥饿.死循环的区别 3.死锁产生的必要条件 4.什么时候会发生死锁 5.死锁的处理策略 2.死锁的处理策略--预防死锁 1.破坏互斥条件 2.破坏不剥夺条件 ...

  5. 10、MySQL锁等待,死锁,死锁检测

    使用数据库时,有时会出现死锁.对于实际应用来说,就是出现系统卡顿. 死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象.就是所谓的锁资源请求产生了回路现象,即死循环,此时称 ...

  6. java 死锁的检测与修复_调查死锁–第4部分:修复代码

    java 死锁的检测与修复 在这个简短的博客系列的最后BadTransferOperation中,我一直在讨论分析死锁,我将修复BadTransferOperation代码. 如果您已经看过本系列的其 ...

  7. 死锁定理与资源分配图化简法

    一 .了解进程资源图 二 .化简资源分配图 方法步骤 第一步:先看系统还剩下多少资源没分配,再看有哪些进程是不阻塞("不阻塞"即:系统有足够的空闲资源分配给它)的 第二步:把不阻塞 ...

  8. 死锁 预防死锁避免死锁_死锁和处理死锁的方法

    死锁 预防死锁避免死锁 僵局 (Deadlock) In the multiprogramming operating system, there are a number of processing ...

  9. 如何判断mysql死锁_MySQL 死锁问题分析

    线上某服务时不时报出如下异常(大约一天二十多次):"Deadlock found when trying to get lock;". Oh, My God! 是死锁问题.尽管报错 ...

最新文章

  1. Thread系列——Thread.Sleep(0)
  2. filezilla 设置服务器_java项目部署到linux服务器,微信小程序后台springboot项目部署到腾讯云服务器(图文详解)...
  3. Html5画布(canvas)实例之绘制矩形
  4. 我精心珍藏的Python代码技巧
  5. java 堆_JAVA学习笔记 07——堆、栈和垃圾回收机制
  6. hadoop3.0.3 SLS-Failed to create an AM
  7. 最新教程:Python开发钉钉群自定义机器人
  8. java 多线程 选择题_Java多线程之三道多线程练习题
  9. XSS-Game level 6
  10. php装箱,PHP实现的装箱算法示例
  11. python写斗地主游戏_基于python的简单斗地主实现-Go语言中文社区
  12. 苏州计算机应用能力中级办公自动化,苏州市计算机应用能力考核(中级-办公自动化)新系统使用..doc_人人文库网...
  13. 计算机考研复试汇总(所有科目)
  14. [Tyvj1450 GF打Dota]
  15. 面试题之细胞分裂问题
  16. 6G八大关键技术(国泰君安团队)
  17. 我来告诉你,那些博客中的gif动态图是怎么弄的?
  18. 电信网通的IP地址分布
  19. springboot学生信息管理的设计与实现毕业设计源码191219
  20. Windows在虚拟机安装苹果MacOS系统

热门文章

  1. obsidian之腾讯云图床+picgo设置指南
  2. Selenium与浏览器驱动安装测试
  3. HTML使用DIV+css实现展开全文的功能
  4. redash二次开发和制作镜像
  5. ios中域名转换为ip地址
  6. 淘宝白菜群催生欺诈购买网赚
  7. realme真我gt能升级鸿蒙系统吗,realme真我GT Neo专为学生党打造,堪称性价比之王...
  8. ESP32那些事儿(六):功能开发之蓝牙及WiFi功能
  9. Python 在一行中输入多个数,用空格隔开
  10. python绘制生日快乐图片_祝自己生日快乐 | 利用Python和R分析一年写作