Java程序会产生死锁?如何定位、修复?

news2024/11/17 9:52:10

文章目录

    • 死锁的概念
    • 死锁定位
    • 实战
      • 模拟问题定位
        • 使用 jstack
        • 使用JConsole
        • 使用 Java 提供的标准管理 API

死锁的概念

  • 死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。死锁不仅仅是在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。

在这里插入图片描述

死锁定位

  • 定位死锁最常见的方式就是利用 jstack 等工具获取线程栈,然后定位互相之间的依赖关系,进而找到死锁。如果是比较明显的死锁,往往 jstack 等就能直接定位,类似 JConsole 甚至可以在图形界面进行有限的死锁检测
  • 如果程序运行时发生了死锁,绝大多数情况下都是无法在线解决的,只能重启、修正程序本身问题。所以,代码开发阶段互相审查,或者利用工具进行预防性排查,往往也是很重要的。

实战

一个基本的死锁程序例子

public class DeadLockSample extends Thread {
	private String first;
	private String second;
	public DeadLockSample(String name, String first, String second) {
    	super(name);
    	this.first = first;
    	this.second = second;
	}
 
	public  void run() {
    	synchronized (first) {
        	System.out.println(this.getName() + " obtained: " + first);
        	try {
            	Thread.sleep(1000L);
            	synchronized (second) {
                	System.out.println(this.getName() + " obtained: " + second);
            	}
        	} catch (InterruptedException e) {
            	// Do nothing
        	}
    	}
	}

	public static void main(String[] args) throws InterruptedException {
		// 死锁样例代码
    	String lockA = "lockA";
    	String lockB = "lockB";
    	DeadLockSample t1 = new DeadLockSample("Thread1", lockA, lockB);
    	DeadLockSample t2 = new DeadLockSample("Thread2", lockB, lockA);
    	t1.start();
    	t2.start();
    	t1.join();
    	t2.join();
	}

}
  • 程序编译执行后,几乎每次都可以重现死锁
    在这里插入图片描述

模拟问题定位

使用 jstack

  • 首先使用 jps 或者系统的 ps 命令、任务管理器等工具,确定进程 ID
jps

在这里插入图片描述

  • 然后,调用 jstack 获取线程栈(jstack在jdk包的bin目录下)
jstack 24468

在这里插入图片描述

"Thread2" #21 prio=5 os_prio=0 tid=0x000000001dfa3000 nid=0x3ab0 waiting for monitor entry [0x0000000020a6f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.carroll.test.thread.DeadLockSample.run(DeadLockSample.java:25)  //具体的类以及代码行数
        - waiting to lock <0x0000000776258c30> (a java.lang.String) // 等待获取锁  <0x0000000776258c30>
        - locked <0x0000000776258c68> (a java.lang.String)  // 已经持有锁  <0x0000000776258c68>

"Thread1" #20 prio=5 os_prio=0 tid=0x000000001dfa2000 nid=0x46f4 waiting for monitor entry [0x000000002096e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.carroll.test.thread.DeadLockSample.run(DeadLockSample.java:25)  //具体的类以及代码行数
        - waiting to lock <0x0000000776258c68> (a java.lang.String) // 等待获取锁  <0x0000000776258c68>
        - locked <0x0000000776258c30> (a java.lang.String) // 已经持有锁  <0x0000000776258c30>
  • 上面这个输出非常明显,找到处于 BLOCKED 状态的线程,按照试图获取(waiting)的锁 ID查找,很快就定位问题。 jstack 本身也会把类似的简单死锁抽取出来,直接打印出来。

实际应用中,类死锁情况未必有如此清晰的输出,但是总体上可以理解为:区分线程状态 -> 查看等待目标 -> 对比 Monitor 等持有状态

使用JConsole

  • 找到jdk包的bin目录,双击打开jconsole
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

使用 Java 提供的标准管理 API

  • ThreadMXBean:Java 虚拟机线程系统的管理接口。

    • Java 虚拟机具有此接口的实现类的单一实例。实现此接口的实例是一个 MXBean,可以通过调用ManagementFactory.getThreadMXBean() 方法或从平台 MBeanServer 方法获得它。
  • 在上面main方法中加入下面的代码片段:

ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
Runnable dlCheck = () -> {
	long[] threadIds = mbean.findDeadlockedThreads();
	if (threadIds != null) {
		ThreadInfo[] threadInfos = mbean.getThreadInfo(threadIds);
		System.out.println("Detected deadlock threads:");
		for (ThreadInfo threadInfo : threadInfos) {
			System.out.println(threadInfo.getThreadName());
		}
	}
};
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// 稍等 5 秒,然后每 10 秒进行一次死锁扫描
scheduler.scheduleAtFixedRate(dlCheck, 5L, 10L, TimeUnit.SECONDS);

在这里插入图片描述

你知道的越多,你不知道的越多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/707367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis - Reactor 模式的事件驱动源码解析

前言 本篇将介绍 redis 服务器中 I/O 复用的具体应用。 redis 服务器将所有需处理的事件抽象为两种事件&#xff1a; 文件事件。redis 服务器是通过 Socket 与客户端进行连接和通信的。文件事件就是服务器对 Socket 的 I/O 操作的一种抽象&#xff0c;包括 accept、recv、sen…

Windows 解决cmd/dos窗口中文乱码问题

文章目录 一、问题描述二、解决方案1. 更改DOS窗口代码页方式1&#xff1a;更改dos窗口代码页&#xff08;临时有效&#xff09;方式2&#xff1a;修改注册表CodePage项&#xff08;永久有效&#xff09;方式3&#xff1a;修改 .lnk 快捷方式的文件属性&#xff08;永久有效&am…

Minkube部署单节点kubernetes-1.23.7

minikube是一个快速构建单节点kubernetes的一个工具&#xff0c;用于快速构建本地测试和开发环境。 1、关闭防火墙和selinux systemctl stop firewalld && systemctl disable firewalld setenforce 0 sed -i /SELINUX/s/enforcing/disabled/g /etc/selinux/config 2…

Vue 项目中使用WebSocket 消息推送

一、功能需求 1.这是我在后台管理项目中使用到的&#xff0c;主要的作用是搞一个消息提醒的功能。 2.主要有右上角的提示和有下角的消息弹框。 3.主要实现的功能是如果用户有未读的消息&#xff0c;那么首次登录就弹框&#xff0c;如果用户关闭了页面&#xff0c;那么再次刷新…

手把手教学使用宝塔面板部署前后端分离项目(全面详细)

前言&#xff1a;平日里我们的前后端项目基本上都是通过linux系统提供的dos命令去部署&#xff0c;有没有一种更简单的方式去部署我们自己的项目呢&#xff0c;答案是有的&#xff0c;本篇博客就是手把手教学如何通过一个可视化的页面去部署我们自己开发的前后端分离项目。 目录…

【Java项目】解决请求路径上明文ID传输导致可能被攻击的方法

文章目录 问题思路解决 问题 这个问题是我公司的一个小业务问题&#xff0c;问题来源于我们发送请求的时候&#xff0c;请求路径上携带的是明文&#xff0c;比如http://xxx/xxx/id12345&#xff0c;那么别有用心的人就可能会推测出id的生成策略&#xff0c;导致遍历id&#xf…

【需求实现】Tensorflow2的曲线拟合(一):数据集分割

神经网络中输入多少数据就输出多少数据的情况如何实现 导读数据集长什么样&#xff1f;怎么分割数据集&#xff1f;时间窗口分析模板我知道你很急&#xff0c;但你先别急 换个思路 导读 在实习的过程中遇到了这样一种需求&#xff1a;给定一条序列&#xff0c;并另外给定一条期…

vue如何封装一个上传多张图片的组件

上传图片不管是后台还是前端小程序&#xff0c;上传图片都是一个比不可少的功能有时候需要好几个页面都要上传图片&#xff0c;每个页面都写一个非常不方便&#xff0c;这时候就没有封装起来用的方便。跟上我的步伐带你了解如何封装 首先&#xff1a;创建一个文件夹在component…

【FFmpeg实战】过滤器 ---- h264_mp4toannexb

原文地址&#xff1a;https://www.cnblogs.com/vczf/p/13818609.html H264有两种封装方式&#xff1a;字节流AnnexB格式 AVCC格式。 1. AnnexB格式 ---- 用于实时播放 开始前缀&#xff08;00000001或000001&#xff09;&#xff0b;NALU数据  绝大部分编码器的默认输出格式…

leetcode题目1481. 不同整数的最少数目

题目 不同整数的最少数目 给你一个整数数组 arr 和一个整数 k 。现需要从数组中恰好移除 k 个元素&#xff0c;请找出移除后数组中不同整数的最少数目。 示例 1&#xff1a; 输入&#xff1a;arr [5,5,4], k 1 输出&#xff1a;1 解释&#xff1a;移除 1 个 4 &#xff0c…

初识消息队列

消息队列 字面意思就是存放消息的队列(Message Queue 简称MQ)&#xff0c;最简单的消息队列模型包括了三个角色&#xff1a; 消息队列&#xff1a;存储和管理信息&#xff0c;也被称为消息代理生产者&#xff1a;发送消息到消息队列消费者&#xff1a;从消息队列中获取消息并…

基于TensorFlow和Keras的狗猫数据集的分类实验

文章目录 前言一、环境配置1、anaconda安装2、修改jupyter notebook工作目录3、配置TensorFlow、Keras 二、数据集分类1、分类源码2、训练流程 三、模型调整1.图像增强2、网络模型添加dropout层 四、使用VGG19优化提高猫狗图像分类1、构建网络模型2、初始化一个VGG19网络实例3、…

C语言--消失的数字

文章目录 1.法一&#xff1a;映射法2.法二&#xff1a;异或法3.法三&#xff1a;差值法4.法四&#xff1a;排序查找 1.法一&#xff1a;映射法 时间复杂度&#xff1a;O&#xff08;N&#xff09; 空间复杂度&#xff1a;O&#xff08;N&#xff09; #include<stdio.h>…

第4章 信息系统管理

文章目录 4.1.1 管理基础1 层次结构2 系统管理 4.1.2 规划和组织1 规划模型2 组织模型1&#xff09;业务战略&#xff08;竞争力优势模型&#xff1a;差异化、总成本领先、专注 战略&#xff09;2&#xff09;组织机制战略&#xff08;莱维特钻石模型&#xff1a;信息与控制、人…

【C++学习】类和对象 | 再谈构造函数 | 构造函数中的隐式类型转换 | static静态成员

目录 1. 再谈构造函数 2. 构造函数中的隐式类型转换 3. static静态成员 写在最后&#xff1a; 1. 再谈构造函数 我们之前使用构造函数初始化&#xff1a; #include <iostream> using namespace std;class Date { public:Date(int year 2023, int month 7, int da…

arcgis js 通过某一个经纬度 定位报错,并且图标变得很大【已解决】

报错 svg.js:42 Error: attribute transform: Expected number, “…0000,0.02102085,NaN,NaN)”. svg.js:49 Error: attribute x: Expected length, “NaN”. svg.js:49 Error: attribute y: Expected length, “NaN”. 图标特别大&#xff0c;也看不到地图 分析 这个方法中…

智驾“平价”,小鹏G6打特斯拉是认真的

作者|张祥威编辑|德新 “小鹏在辅助驾驶领域不是遥遥领先&#xff0c;而是领先友商 12 - 36 个月。” “希望L4的能力能够在2027年到来&#xff0c;或者更早一点。” “G6的销量肯定要过万&#xff0c;这是最起码的。” G6上市发布期间&#xff0c;小鹏的高管各种喊话。 抛开80…

(嵌入式)STM32G061C8T6、STM32G061C6T6、STM32G061C8U6 64MHz 64KB/32KB 闪存(MCU)

STM32G0 32位微控制器 (MCU) 适合用于消费、工业和家电领域的应用&#xff0c;并可随时用于物联网 (IoT) 解决方案。这些微控制器具有很高的集成度&#xff0c;基于高性能ARM Cortex-M0 32位RISC内核&#xff0c;工作频率高达64MHz。该器件包含内存保护单元 (MPU)、高速嵌入式内…

算法笔记--滑动窗口

力扣209.长度最小子数组 https://leetcode.cn/problems/minimum-size-subarray-sum/ 在这道题中要注意的不仅仅是滑动窗口的问题&#xff0c;更重要的问题是在循环控制中&#xff0c;不恰当的语法使用会导致这道题出现很严重的问题&#xff0c;这导致我做这道题做了很多天&…

亿级数据毫秒级响应?

作为一名深陷在增删改查泥潭中练习时长三年的夹娃练习生&#xff0c;偶尔会因为没有开发任务不知道周报写什么而苦恼。 正愁这周写啥呢&#xff0c;组长过来交代了个跟进第三方公司性能测试报告的工作&#xff0c;我一寻思这活不最好干了吗&#xff0c;正愁不知道周报咋写呢&a…