多线程中死锁是如何产生的?如何检测?如何避免?

一、死锁是如何产生的?

死锁:是指两个或多个线程在执行过程中,因争夺资源而造成的一种僵局。具体来说,每个线程持有一部分资源,并等待其他线程所持有的资源释放,导致所有线程都无法继续执行。

例如:

线程A 获得 lockX 对象锁,接下来想获取 lockY对象的锁;

线程B 获得 lockY 对象锁,接下来想获取 lockX对象的锁。

代码如下:

public class DeadlockTest {

    private static Object lockX = new Object();
    private static Object lockY = new Object();

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            synchronized (lockX) {
                System.out.println("Thread A: Holding lock X...");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("Thread A: Waiting for lock Y...");
                synchronized (lockY) {
                    System.out.println("Thread A: Holding lock X and lock Y...");
                }
            }
        }, "threadA"); // 线程起别名

        Thread threadB = new Thread(() -> {
            synchronized (lockY) {
                System.out.println("Thread B: Holding lock Y...");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                System.out.println("Thread B: Waiting for lock X...");
                synchronized (lockX) {
                    System.out.println("Thread B: Holding lock Y and lock X...");
                }
            }
        }, "threadB");

        threadA.start();
        threadB.start();
    }

}

控制台输出结果:

此时程序并没有结束,这种现象就是死锁现象...线程A持有lock X锁等待获取lock Y锁,线程B持有lock Y锁等待获取lock X锁。  


二、如何进行死锁诊断?

当程序出现了死锁现象,我们可以使用jdk自带的工具:jps和 jstack

步骤如下:

第一:查看运行的线程

打开终端,运行命令:jps,得到Java进程的PID、主类的完整名称。

第二:使用jstack查看线程运行的情况 

运行命令:jstack -l 18348

发现一个死锁: 


三、如何避免死锁?

预防死锁

预防死锁的策略是破坏死锁的四个必要条件之一:

  1. 互斥条件:确保资源可以被同时访问,不过并非所有资源都能够做到这一点。
  2. 请求与保持条件:一次性申请所有资源,不允许分步申请。
  3. 不可剥夺条件:一旦资源被分配给某线程,就不应该从该线程中强制夺回。
  4. 循环等待条件:对资源实施一个全局的顺序,确保所有线程按顺序申请资源。

避免死锁

避免死锁的策略是在运行时避免系统进入不安全状态。银行家算法是一个著名的避免死锁的算法,它通过动态分析资源分配来确保系统始终处于安全状态。


四、解决死锁示例:

在上面的例子中,如果线程A和线程B几乎同时开始执行,它们可能会相互等待对方释放锁,从而导致死锁。

解决这个问题的一种方法是确保所有线程按相同的顺序获取锁:

public class DeadlockResolvedDemo {

    private static Object lockX = new Object();
    private static Object lockY = new Object();

    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            synchronized (lockX) {
                System.out.println("Thread A: Holding lock X...");

                try { Thread.sleep(100); } catch (InterruptedException e) {}

                System.out.println("Thread A: Waiting for lock Y...");
                synchronized (lockY) {
                    System.out.println("Thread A: Holding lock X and lock Y...");
                }
            }
        });

        Thread threadB = new Thread(() -> {
            synchronized (lockX) { // 注意这里也是先获取lockX
                System.out.println("Thread B: Holding lock X...");

                try { Thread.sleep(100); } catch (InterruptedException e) {}

                System.out.println("Thread B: Waiting for lock Y...");
                synchronized (lockY) {
                    System.out.println("Thread B: Holding lock X and lock Y...");
                }
            }
        });

        threadA.start();
        threadB.start();
    }
}

在这个修改后的例子中,无论线程A还是线程B,都是先尝试获取lockX,然后再获取lockY,这样就打破了循环等待条件,从而避免了死锁。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

马斯克“赛博皮卡”Cybertruck交付!43万起售,性能强如猛兽

原创 | 文 BFT机器人 埃隆马斯克常常被称为是“天才与疯子”的结合,一直是一个争议不断的人物。他九十年代创办电子支付公司;2004年成立特斯拉,开创了一个汽车领域的新时代;人到中年又扬言要发射卫星建立全球无线网…… 许多科技…

Python必备神器揭秘:15个最热门库全解析

更多资料获取 📚 个人网站:ipengtao.com Python生态系统中拥有大量优秀的库,为开发者提供了广泛且强大的工具。本文将介绍15个最受欢迎的Python库,包括它们的功能、优点以及示例代码,帮助读者更全面地了解和使用这些库…

游戏开发常见算法

1.根据权重获取不同的值: 算法思想: 代码实现: _proto.randWeightEnemy function (enemyIdMap, enemyIds, targetWeight, weightArray, monsterNumLimit) {console.log("目标权重值"targetWeight); //targetWeight的值为1700var r…

基于SpringBoot实现的电影院售票系统

一、 系统架构 前端:html | jquery | bootstrap 后端:springboot | thymeleaf | spring-data-jpa 环境:jdk1.8 | mysql | maven 二、代码及数据库 三、功能介绍 01. 首页 02. 登录页 03. 管理端-电影列表 04. 管理端-添加电影 05. 管…

[PyTorch][chapter 4][李宏毅深度学习][Gradient Descent]

前言: 目录: 1: 梯度下降原理 2: 常见问题 3: 梯度更新方案 4: 梯度下降限制 一 梯度下降原理 机器学习的目标找到最优的参数,使得Loss 最小 为什么顺着梯度方向loss 就能下降了。主要原理是泰勒公式。 假设损失函数为 忽略二阶导数, 当 …

【Python】创建简单的Python微服务Demo与FastAPI

创建简单的Python微服务Demo与FastAPI 在微服务架构中,通过FastAPI框架创建一个简单的Python微服务Demo涉及多个步骤,包括定义服务、使用框架、进行通信等。在这篇文章中,我们将使用FastAPI框架创建两个简单的微服务,它们通过RES…

k8s部署单机模式的minio

k8s部署单机模式的minio 一、说明二、yaml内容三、步骤3.1 创建资源3.2 查看启动日志3.2 查看svc并访问控制台 一、说明 项目使用minio,准备在k8s环境部署一套minio试用。 1.关于minio的原理和概念参考: https://mp.weixin.qq.com/s?__bizMzI3MDM5NjgwNg&mid…

zabbix6.4监控交换机发现ICMP报错Ping item must have target or host interface specified

报错信息: 查看监控项: 修改键值: 保存再次检查,发现又报错/usr/sbin/fping: [2] No such file or directory 原因是,zabbix-server上没有安装fping工具 解决方法:yum install fping -y 之后数据采集正常…

Retrofit的转换器

一、前言 1.为什么要使用Retrofit转换器 在我们接受到服务器的响应后,目前无论是OkHttp还是Retrofit都只能接收到String字符串类型的数据,在实际开发中,我们经常需要对字符串进行解析将其转变为一个JavaBean对象,比如服务器响应…

12、pytest上下文友好的输出

官方实例 # content of test_assert2.py import pytestdef test_set_comparison():set1 set("1308")set2 set("8035")assert set1 set2def test_dict_comparison():dict_1 {name:陈畅,sex:男}dict_2 {name:赵宁,sex:女}assert dict_1 dict_2def tes…

神经网络常用归一化和正则化方法解析(一)

🎀个人主页: https://zhangxiaoshu.blog.csdn.net 📢欢迎大家:关注🔍点赞👍评论📝收藏⭐️,如有错误敬请指正! 💕未来很长,值得我们全力奔赴更美好的生活&…

代理IP和网络加速器的区别有哪些

随着互联网的普及,越来越多的人开始使用网络加速器来提高网络速度。然而,很多人并不清楚代理IP和网络加速器之间的区别。本文将详细介绍两者的概念及区别。 一、代理IP 代理IP是一种通过代理服务器进行网络连接的方式。在使用流冠代理IP时,用…

伴随高性能多级网关和多级分布式缓存架构应用实战经验

随着互联网业务的快速发展,对于高性能网络架构的需求越来越迫切。在这篇文章中,我们将介绍高性能多级网关和多级分布式缓存架构在实际应用中的经验,并提供相关示例代码。 一、高性能多级网关的设计与实现 高性能多级网关是一个重要的网络架构…

软件外包公司的核心竞争力

软件外包公司的核心竞争力可以涵盖多个方面,这取决于公司的战略、专业领域和市场定位。以下是一些可能构成软件外包公司核心竞争力的因素,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1…

js中hasOwnProperty() 方法详解

hasOwnProperty 会返回一个布尔值,判断对象中是否存在该属性,不是继承属性,和原型链上的属性,是对象自身的属性,有返回true,没有返回false hasOwnProperty() 方法是 Object 的原型方法(也称实例方法),它定义在 Object.prototype 对象之上&am…

动能资讯 | 智慧汽车—城市NOA迎爆发

在特斯拉引领的 TransformerBev 架构驱动下,智驾算法趋近于端到端的智驾大模型,使得智能驾驶开始步入城市 NOA 新时代。 消费者认知增强,未来市场空间广阔。伴随城市 NOA 在 23-24 年的落地和普及、L3 法规在年内的落地,行业 0-1…

众里寻她千百度:使用Excalidraw一句话绘制进销存系统采购入库流程

引言: 本文将介绍如何使用Excalidraw这一在线绘图工具来绘制进销存系统中的采购入库流程,帮助您更好地理解和优化采购流程。 正文: 1. 打开Excalidraw网站: 在浏览器中输入"https://excalidraw.com",打开Ex…

聚观早报 |真我GT5 Pro细节曝光;iQOO Neo9系列参数曝光

【聚观365】12月5日消息 真我GT5 Pro细节曝光 iQOO Neo9系列参数曝光 抖音商城双12好物节 蔚来正式获得独立造车资质 三星Galaxy S24 Ultra手写笔获认证 真我GT5 Pro细节曝光 今年的顶级旗舰大比拼也进入最后的高潮,剩余还未亮相的骁龙8 Gen3旗舰新机目前也基…

个体诊所电子处方系统哪个好用,推荐一款可以自由设置配方模板能够填写病历可以查询历史病历的门诊处方笺软件

一、前言 1、功能实用,操作简单,不会电脑也会操作,软件免安装,已内置数据库。 2、中医西医均可用此软件开电子处方,支持病历记录查询,药品进出库管理,支持配方模板一键导入电子处方。 二、电子…

Java 基础学习(五)面向对象编程-对象和类

1 类和对象 1.1 面向对象概述 1.1.1面向对象简史 面向对象编程思想最初的起源可以追溯到1960年的Simula语言,这被认为是第一个支持面向对象编程概念的语言。Simula引入了类、对象、继承等概念,将数据和操作进行封装。Simula的创始人奥利-约翰达尔&…