【并发编程】什么是死锁?死锁如何解决?线上发生死锁应该怎么办?

news2024/12/23 19:05:04

📫作者简介:小明Java问道之路2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。

           

🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人

🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家

         

 🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~ 


🍅 文末获取联系 🍅  👇🏻 精彩专栏推荐订阅收藏 👇🏻

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

🔥Redis从入门到精通与实战🔥

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

🔥MySQL从入门到精通🔥

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

🔥计算机底层原理🔥

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

🔥数据结构与企业题库精讲🔥

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

🔥互联网架构分析与实战🔥

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

🔥Java全栈白宝书🔥

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

本文目录

本文导读

一、死锁是什么?

二、死锁的 4 个必要条件

三、死锁的修复策略

1、避免策略

2、检测与恢复策略

四、线上发生死锁应该怎么办

五、如何用命令行和代码定位死锁?

1、jstack命令

2、ThreadMXBean

总结


本文导读

本文讲解死锁是什么,死锁产生的4个条件以及如何避免死锁,并根据实际线上发生死锁应该怎么办,如何用命令行和代码定位死锁进行讲解。

一、死锁是什么?

死锁是指两个或多个线程(进程)在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

二、死锁的 4 个必要条件

互斥条件:每个资源每次只能被一个线程(或进程,下同)使用,如果每个人都可以拿到想要的资源,那就不需要等待,所以是不可能发生死锁的。

请求与保持条件:当一个线程试图获取资源,但发生了阻塞,则需对已获得的资源保持不放。如果在请求资源时阻塞了,并且会自动释放手中资源(例如锁)的话,那别人自然就能拿到我刚才释放的资源,也就不会形成死锁。

不剥夺条件:它是指线程已获得的资源,在未使用完之前,不会被强行剥夺。

循环等待条件:通俗得讲就是多个线程之间必须形成“循环等待”,才有可能形成死锁,比如在两个线程之间,这种“循环等待”就意味着它们互相持有对方所需的资源、互相等待。

三、死锁的修复策略

1、避免策略

避免策略最主要的思路就是,优化代码逻辑,从根本上消除发生死锁的可能性。通常而言,发生死锁的一个主要原因是顺序相反的去获取不同的锁。因此大家获取锁的顺序就一样了,就不会出现获取锁顺序相反的情况

synchronized (from) {
     synchronized (to) {
     }
}

2、检测与恢复策略

一旦发生死锁,就可以用死锁恢复机制(用命令行和代码定位死锁),比如剥夺某一个资源,来解开死锁,进行恢复;线程终止;资源抢占(让线程回退几步、 释放资源)。

四、线上发生死锁应该怎么办

如果线上发生死锁问题,最好的办法是保存 JVM 信息、日志等“案发现场”的数据,然后立刻重启服务,来尝试修复死锁。

为什么说重启服务能解决问题?因为发生死锁往往要有很多前提条件的,并且当并发度足够高的时候才有可能会发生死锁,所以重启后再次立刻发生死锁的几率并不是很大,当我们重启服务器之后,就可以暂时保证线上服务的可用,然后利用刚才保存过的案发现场的信息,排查死锁、修改代码,最终重新发布。

五、如何用命令行和代码定位死锁?

1、jstack命令

jstack pid是查看Java 线程的一些相关信息,如果是比较明显的死锁关系,那么这个工具就可以直接检测出来;

如果死锁不明显,那么它无法直接检测出来,不过我们也可以借此来分析线程状态,进而就可以发现锁的相互依赖关系,所以这也是很有利于我们找到死锁的方式。

jstack 可以找到死锁,把哪个线程、想要获取哪个锁、形成什么样的环路展示出来,当我们有了这样的信息之后,死锁就非常容易定位了,所以接下来我们就可以进一步修改代码,来避免死锁了。

打印:
Found one Java-level deadlock:
=============================
"t2": waiting to lock monitor 0x00007fa06c004a18 (object 0x000000076adabaf0, a java.lang.Object),
  which is held by "t1"
"t1": waiting to lock monitor 0x00007fa06c007358 (object 0x000000076adabb00, a java.lang.Object),
  which is held by "t2"
Java stack information for the threads listed above:
===================================================
"t2": at lesson67.MustDeadLock.run(MustDeadLock.java:31)
- waiting to lock <0x000000076adabaf0> (a java.lang.Object)
- locked <0x000000076adabb00> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)
"t1": at lesson67.MustDeadLock.run(MustDeadLock.java:19)
- waiting to lock <0x000000076adabb00> (a java.lang.Object)
- locked <0x000000076adabaf0> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock

2、ThreadMXBean

使用 ThreadMXBean 可以检测程序中出现死锁的线程,获取该线程的相关信息。相比较于jstack 在命令中查看,此种写代码的方式,能够在线程出现死锁的时候,做一些对应的操作

通过 ThreadMXBean 的 findDeadlockedThreads 方法,可以获取到一个 deadlockedThreads 的数组,然后进行判断,当这个数组不为空且长度大于 0 的时候,我们逐个打印出对应的线程信息

比如我们打印出了线程 id,也打印出了线程名,同时打印出了它所需要的那把锁正被哪个线程所持有,在业务代码中加入这样的检测,那我们就可以在发生死锁的时候及时地定位,同时进行报警等其他处理。

public static void main(String[] args) throws InterruptedException {
	ThreadMXBeanDetection r1 = new ThreadMXBeanDetection();
	ThreadMXBeanDetection r2 = new ThreadMXBeanDetection();

	//给不同的线程, 设置不同的标记位
	r1.flag=1;
	r2.flag=2;
	Thread t1 = new Thread(r1);
	Thread t2 = new Thread(r2);
	t1.start();
	t2.start();

	//让两个子线程执行
	Thread.sleep(1000);
	ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();

	//获取发生死锁的线程id数组
	long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();

	//判断发生死锁的线程是否为空
	if (deadlockedThreads != null && deadlockedThreads.length > 0) {
		for (int i = 0; i < deadlockedThreads.length; i++) {

			//传入发生死锁的线程id , 获取发生死锁的线程信息
			ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]);

			//打印出发生死锁线程的名称
			System.out.println("线程id为"+threadInfo.getThreadId()+",死锁线程名为" + threadInfo.getThreadName()+"的线程已经发生死锁,需要的锁正被线程"+threadInfo.getLockOwnerName()+"持有。");
		}
	}
}

总结

本文讲解死锁是什么,死锁产生的4个条件以及如何避免死锁,并根据实际线上发生死锁应该怎么办,如何用命令行和代码定位死锁进行讲解。

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

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

相关文章

Simple_SSTI_1-WEB-bugku-解题步骤

——CTF解题专栏—— 声明&#xff1a;文章由作者weoptions学习或练习过程中的步骤及思路&#xff0c;非正式答案&#xff0c;仅供学习和参考。 题目信息&#xff1a; 题目&#xff1a;Simple_SSTI_1 作者&#xff1a;valecalida 提示&#xff1a;无 场景&#xff1a; 解题…

面试数据库八股文十问十答第一期

面试数据库八股文十问十答第一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 1.MySQL常见索引、 MySQL常见索引有: 主键索引、唯一索引、普通索引、全文索引、组合索引(最左前缀)主键索引特点&#xff1a;唯一性&#xff0c;非空&#xff0c;自增&#xff08;如果使用…

Azure Machine Learning - 使用 REST API 创建 Azure AI 搜索索引

本文介绍如何使用 Azure AI 搜索 REST AP和用于发送和接收请求的 REST 客户端以交互方式构建请求。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&…

Python zip函数及用法与lambda表达式及用法

Python zip函数及用法 zip() 函数可以把两个列表“压缩”成一个 zip 对象&#xff08;可迭代对象&#xff09;&#xff0c;这样就可以使用一个循环并行遍历两个列表。为了测试 zip() 函数的功能&#xff0c;我们可以先在交互式解释器中“试验”一下该函数的功能。 >>&g…

自定义类型-结构体,联合体和枚举-C语言

引言 能看到结构体&#xff0c;说明C语言想必学习的时间也不少了&#xff0c;在之前肯定也学习过基本数据类型&#xff0c;包括整型int&#xff0c;浮点型float等等。可是在日常生活中&#xff0c;想要描述一个事物并没有那么简单。比如&#xff0c;你要描述一本书&#xff0c…

简单搭建Python开发环境

Python环境安装 Python官网: Welcome to Python.org 1. 选择Python3.x版本下载&#xff0c;建议使用稳定版3.9.13&#xff08;Stable Releases&#xff09;&#xff0c;绝大数库对3.9版本Python已良好支持&#xff0c;但对3.10及以上支持不完全&#xff1a; https://www.…

【【FPGA 之 MicroBlaze 自定义IP核 之 呼吸灯实验】】

FPGA 之 MicroBlaze 自定义IP核 之 呼吸灯实验 通过创建和封装 IP 向导的方式来自定义 IP 核&#xff0c;支持将当前工程、工程中的模块或者指定文件目录封装成 IP 核&#xff0c;当然也可以创建一个带有 AXI4 接口的 IP 核&#xff0c;用于 MicroBlaze 软核处理器和可编程逻辑…

误用STM32串口发送标志位 “USART_FLAG_TXE” “USART_FLAG_TC”造成的BUG

当你使用串口发送数据时是否出现过这样的情况&#xff1a; 1.发送时第一个字节丢失。 2.发送时出现莫名的字节丢失。 3.各种情况字节丢失。 1.先了解一下串口发送的流程图&#xff08;手动描绘&#xff09;&#xff1a; 可以假想USART_FLAG_TXE是用于检测"弹仓"&…

8、内部FLASH模拟EEPROM实验(STM32F407)

STM32编程方式 在线编程&#xff08;ICP,In-Circuit Programming&#xff09;: 通过JTAG/SWD协议或者系统加载程序(Bootloader)下载用户应用程序到微控制器中。 在程序中编程(IAP,In Application Programming):通过任何一种通信接口(如IO端口,USB,CAN,UART,I2C,SPI等)下载程…

记录 | photoshop移动选区

期望达到的效果&#xff1a; 选择一块区域&#xff0c;并移动它 操作&#xff1a; (1) 选择矩形选框工具&#xff0c; (2) 对区域进行选取&#xff0c; (3) 选择移动工具&#xff0c; (4) 移动选区&#xff0c;效果如下&#xff0c;

LED屏幕信息安全如何预防?

随着科技的不断进步&#xff0c;LED屏幕在我们生活和工作中扮演着越来越重要的角色&#xff0c;然而&#xff0c;随之而来的是信息安全面临的挑战。为了有效预防LED屏幕信息的泄露和被盗取&#xff0c;我们需要采取一系列的安全措施。以下是一些建议&#xff1a; 物理安全措施&…

VSCode主题自定义

记录vscode主题配置 {"editor.minimap.enabled": true,"files.autoSave": "afterDelay","security.workspace.trust.untrustedFiles": "open","markdown-preview-enhanced.previewTheme": "atom-light.css&…

oracle sql相关语法

SQL*PLUS 在SQL*PLUS执行&#xff0c;会在执行后显示查询的执行计划和统计信息 SET AUTOTRACE ON;SELECT * FROM your_table WHERE column_name value;SET AUTOTRACE OFF;PLSQL PLSQL查询sql界面&#xff0c;鼠标右键&#xff0c;点击执行计划&#xff0c;会出现sql的执行计…

09-命令者模式-C语言实现

命令者模式是一个高内聚的模式&#xff0c; 其定义为&#xff1a; Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.&#xff08;将一个请求封装成一个对象&…

非得让你会之MyBatis插件与Java动态代理

引言 咱们今天聊聊Java动态代理&#xff0c;这东西在开发中真的太常见了。比如Spring AOP、RPC&#xff0c;它们都离不开动态代理。然后&#xff0c;咱们再来说说MyBatis插件&#xff0c;这可是MyBatis框架中的一个超实用的功能&#xff0c;它就像是给MyBatis加了个“超能力”…

卷积的理解,卷积与通道的关系

神经网络中的卷积操作卷积在图像领域的功能单通道卷积多通道卷积&#xff08;1个卷积核&#xff09;多通道卷积&#xff08;多个卷积核&#xff09;总结扩展 图像处理中的卷积核恒等&#xff08;Identity&#xff09;边缘检测&#xff08;Edge detection&#xff09;锐化&#…

2243:Knight Moves

文章目录 题目描述思路1. DFS2. BFS3. 动态规划 解题方法1. DFS2. BFS3. 动态规划 题目描述 题目链接 翻译如下&#xff1a; 注&#xff1a;骑士移动是和象棋里的马一样走的是日字型 你的一个朋友正在研究旅行骑士问题 &#xff08;TKP&#xff09;&#xff0c;你要找到最短的…

java学习part28线程安全Lock锁方式

138-多线程-线程安全的懒汉式_死锁_ReentrantLock的使用_哔哩哔哩_bilibili 1.lock类变量 2.使用方法 和以前的加锁一样&#xff0c;同步代码前加锁&#xff0c;代码后解锁&#xff0c;就表示锁住了这一块代码。 lock是上面声明的静态常量 3.同步和加锁对比

通义千问 模型学习 和 SDK试用

通义千问-14B-Chat-Int4 模型库 (modelscope.cn) **通义千问-14B&#xff08;Qwen-14B&#xff09;**是阿里云研发的通义千问大模型系列的140亿参数规模的模型。Qwen-14B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样&#xff0…

2023年第十二届数学建模国际赛小美赛C题雪崩防范求解分析

2023年第十二届数学建模国际赛小美赛 C题 雪崩防范 原题再现&#xff1a; 雪崩是极其危险的现象。现在&#xff0c;我们对雪崩是如何形成的已经有了很好的理解&#xff0c;但是我们还不能详细地预测雪崩发生的原因、时间和地点。村庄和道路可以通过各种方式防止雪崩。避免在脆…