Java 死锁的原理、检测和解决死锁

news2024/11/14 18:46:48

什么是死锁

两个或者多个线程互相持有对方所需要的资源(锁),都在等待对方执行完毕才能继续往下执行的时候,就称为发生了死锁,结果就是两个进程都陷入了无限的等待中。

一般是有多个锁对象的情况下并且获得锁顺序不一致造成的。

死锁产生的条件

死锁产生有四个必要条件,只要系统发生死锁则以上四个条件都必须成立。

  1. 互斥条件: 资源是独占的且排他使用,线程互斥使用资源,即任意时刻一个资源只能给一个线程使用,其他线程若申请一个资源,而该资源被另一线程占有时,则申请者等待直到资源被占有者释放。
  2. 不可剥夺条件: 线程所获得的资源在未使用完毕之前,不被其他线程强行剥夺,而只能由获得该资源的线程资源释放。
  3. 请求和保持条件: 线程每次申请它所需要的资源,在申请新的资源的同时,继续占用已分配到的资源。
  4. 循环等待条件: 在发生死锁时必然存在一个线程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个线程等待环路,环路中每一个线程所占有的资源同时被另一个申请,也就是前一个线程占有后一个线程所申请的资源。

检测死锁

构造死锁

public class DeadLockTest {
    public static Object lockObj1 = new Object();
    public static Object lockObj2 = new Object();

    public static void main(String[] args) {
        Runnable r1 = DeadLockTest::lock1;
        Thread t1 = new Thread(r1);
        t1.setName("deadLockThread1");


        Runnable r2 = DeadLockTest::lock2;
        Thread t2 = new Thread(r2);
        t2.setName("deadLockThread2");

        t1.start();
        t2.start();
    }

    public static void lock1() {
        try {
            synchronized (lockObj1) {
                System.out.println(Thread.currentThread().getName() + "进入lock1");
                TimeUnit.SECONDS.sleep(5);
                lock2();
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static void lock2() {
        try {
            synchronized (lockObj2) {
                System.out.println(Thread.currentThread().getName() + "进入lock2");
                TimeUnit.SECONDS.sleep(5);
                lock1();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

检测死锁

JConsole

JConsole是Java 5 开始提供。

启动JConsole: JAVA_HOME\bin\jconsole.exe
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JStack

JStack位于:JAVA_HOME\bin\jstack.exe

Found one Java-level deadlock: 描述了死锁线程名称和等待的锁持有者;
Java stack information for the threads listed above:描述了死锁线程的堆栈信息。

Administrator@DESKTOP-CKPKB5K MINGW64 ~
$ jps
4512 GradleDaemon
12136 Launcher
13592
16760 Jps
15916 DeadLockTest

Administrator@DESKTOP-CKPKB5K MINGW64 ~
$ jstack -l 15916|grep 'deadlock' -A 50
Found one Java-level deadlock:
=============================
"deadLockThread2":
  waiting to lock monitor 0x0000021b98303fb8 (object 0x00000000f9c9ae20, a java.lang.Object),
  which is held by "deadLockThread1"
"deadLockThread1":
  waiting to lock monitor 0x0000021b98301938 (object 0x00000000f9c9ae30, a java.lang.Object),
  which is held by "deadLockThread2"

Java stack information for the threads listed above:
===================================================
"deadLockThread2":
        at tech.pplus.cases.lock.DeadLockTest.lock1(DeadLockTest.java:33)
        - waiting to lock <0x00000000f9c9ae20> (a java.lang.Object)
        at tech.pplus.cases.lock.DeadLockTest.lock2(DeadLockTest.java:49)
        - locked <0x00000000f9c9ae30> (a java.lang.Object)
        at tech.pplus.cases.lock.DeadLockTest$$Lambda$2/1104106489.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)
"deadLockThread1":
        at tech.pplus.cases.lock.DeadLockTest.lock2(DeadLockTest.java:47)
        - waiting to lock <0x00000000f9c9ae30> (a java.lang.Object)
        at tech.pplus.cases.lock.DeadLockTest.lock1(DeadLockTest.java:35)
        - locked <0x00000000f9c9ae20> (a java.lang.Object)
        at tech.pplus.cases.lock.DeadLockTest$$Lambda$1/2047329716.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:750)

Found 1 deadlock.

解决死锁

使用Lock#tryLock(long, java.util.concurrent.TimeUnit)

破坏死锁产生的“循环等待条件”条件,设置最大等待锁时间以及处理获取锁失败。

改造代码锁的实现:

public class SolveDeadLockTest {
    public static ReentrantLock lockObj1 = new ReentrantLock();
    public static ReentrantLock lockObj2 = new ReentrantLock();
    ;

    public static void main(String[] args) {
        Runnable r1 = SolveDeadLockTest::lock1;
        Thread t1 = new Thread(r1);
        t1.setName("deadLockThread1");


        Runnable r2 = SolveDeadLockTest::lock2;
        Thread t2 = new Thread(r2);
        t2.setName("deadLockThread2");

        t1.start();
        t2.start();
    }

    public static void lock1() {
        try {
            if (lockObj1.tryLock(3, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + "进入lock1");
                TimeUnit.SECONDS.sleep(5);
                lock2();
            }else {
                System.out.println(Thread.currentThread().getName() + "进入lock1失败,原因:获取锁失败!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static void lock2() {
        try {
            if (lockObj2.tryLock(3, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getName() + "进入lock2");
                TimeUnit.SECONDS.sleep(5);
                lock1();
            }else {
                System.out.println(Thread.currentThread().getName() + "进入lock2失败,原因:获取锁失败!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

deadLockThread1进入lock1
deadLockThread2进入lock2
deadLockThread2进入lock1失败,原因:获取锁失败!
deadLockThread1进入lock2失败,原因:获取锁失败!

Process finished with exit code 0

线程都正常结束,并没有产生死锁。

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

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

相关文章

微服务+springcloud+springcloud alibaba学习笔记【Spring Cloud Gateway服务网关】(7/9)

Spring Cloud Gateway服务网关 7/9 1、GateWay概述2、GateWay的特性:3、GateWay与zuul的区别:4、zuul1.x的模型:5、什么是webflux:6、GateWay三大概念:6.1,路由:6.2,断言:6.3,过滤: 7、GateWay的工作原理:8、使用GateWay:8.1,建module8.2,修改pom文件8.3,写配置文件8.4,主启动类…

微服务学习——微服务框架

Nacos配置管理 统一配置管理 配置更改热更新 将配置交给Nacos管理的步骤&#xff1a; 在Nacos中添加配置文件在微服务中引入nacos的config依赖在微服务中添加bootstrap.yml&#xff0c;配置nacos地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去nacos读取哪个…

Java:JDK对IPv4和IPv6处理介绍

以下以JDK8为例说明对IPv4和IPv6是如何处理的。 一、常用代码 一般情况下&#xff0c;使用如下代码可以获取到域名/主机名对应的多个IP&#xff0c;其中部分是IPv4的&#xff0c;部分是IPv6的&#xff1a; try {InetAddress[] addrs InetAddress.getAllByName(host);for (I…

Quartz框架详解分析

文章目录 1 Quartz框架1.1 入门demo1.2 Job 讲解1.2.1 Job简介1.2.2 Job 并发1.2.3 Job 异常1.2.4 Job 中断 1.3 Trigger 触发器1.3.1 SimpleTrigger1.3.2 CornTrigger 1.4 Listener监听器1.5 Jdbc store1.5.1 简介1.5.2 添加pom依赖1.5.3 建表SQL1.5.4 配置文件quartz.propert…

23-HTTP协议

目录 1.HTTP是什么&#xff1f; 2.HTTP工作过程 3.HTTP协议格式 3.1.抓包工具使用 eg&#xff1a;抓取"必应"的包 PS&#xff1a;HTTP不同版本号之间的区别 3.2.抓包工具原理 3.3.抓包结果分析 ①HTTP 请求&#xff1a; ②HTTP 响应&#xff1a; 3.4.协议…

ArduPilot Kakute F7 AIO DIYF450 without GPS配置

ArduPilot Kakute F7 AIO DIYF450 without GPS配置 1. 源由2. 配置2.1 Kakute F7 AIO相关配置2.1.1 串口规划2.1.2 电传配置2.1.3 GPS配置2.1.4 CRSF接收机配置2.1.5 Compass配置2.1.6 电机配置2.1.7 TX12 遥控器配置 3. 实测效果4. 参考资料 1. 源由 鉴于GPS模块信号质量未达…

3DEXPERIENCE云可以为PLM带来什么?

在消费者领域&#xff0c;云的优势已显而易见&#xff0c;用一个词就可以概括&#xff1a;便利&#xff0c;3DEXPERIENCE云存储服务的用户可以从任何位置在任何设备上访问其数据&#xff0c;只要能够连接到互联网就行了。在一台设备 上所做的更改会立即反映在另一台设备上。 同…

提升10倍写作效率,这5个写作工具,文笔不好的人别错过

记得刚出来上班的时候&#xff0c;我的写作效率很低&#xff0c;经常没有思路&#xff0c;也找不到选题。甚至一两个小时过去了&#xff0c;仍然不知道如何动笔&#xff0c;经常写了删&#xff0c;删了又写。工欲善其事&#xff0c;必先利其器。在写作过程中&#xff0c;需要一…

【数据分析之道-NumPy(五)】numpy迭代数组

文章目录 专栏导读1、前言2、使用python循环语句3、使用nditer函数3.1迭代一维数组3.2迭代二维数组3.3迭代指定顺序的数组3.4迭代时修改数组中的元素 4、使用flat属性5、使用ndenumerate函数6、使用布尔索引总结 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN Python…

IO多路复用—多线程网络并发通信 select poll epoll

1.IO 多路转接 (复用) ​ IO 多路转接也称为 IO 多路复用&#xff0c;它是一种网络通信的手段&#xff08;机制&#xff09;&#xff0c;通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的&#xff0c;一旦检测到有文件描述符就绪&#xff08; 可以读数据或者可以写…

Nginx企业级使用1(运维笔记)

Nginx企业级使用1&#xff08;运维笔记&#xff09; 重装和升级 信号参数 Kill 选项参数 pid ##关闭nginx ##快速关闭 kill -INT pid ##优雅关闭 kill -QUIT pid##############实操############## [rootserver01 ~]# ps -ef|grep nginx root 1668 1 0 11:09 ?…

Flask入门和视图--01

1. 概述 虚拟环境搭建和使用 Flask框架的特点&#xff0c;Flask框架的组成 Flask框架中MVT模式开发 蓝图Blueprint的使用 路由Route的使用 请求Request和响应Response的使用 2. Flask简介 2.1 简介 Python后端的2个主流框架:Flask 轻量级框架Django 重型框架Flask是一…

开心档之C++ 信号处理

C 信号处理 目录 C 信号处理 signal() 函数 实例 raise() 函数 实例 信号是由操作系统传给进程的中断&#xff0c;会提早终止一个程序。在 UNIX、LINUX、Mac OS X 或 Windows 系统上&#xff0c;可以通过按 CtrlC 产生中断。 有些信号不能被程序捕获&#xff0c;但是下表…

安全狗入选2023年福建省数字经济核心产业领域创新企业名单

近日&#xff0c;福建省数字福建建设领导小组办公室公布了入选2023年全省数字经济核心产业领域创新企业名单。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借综合表现与优势入选名单&#xff0c;荣膺“未来独角兽”称号。 据悉&#xff0c;此次对“未来独角兽”的评选条件…

调频电视发射机工作原理

我们平常所接触到的电视信号无线传输器材&#xff0c;较多采用调幅方式。原因是调幅方式在整个电视技术领域用得比较普遍&#xff0c;如我们生活中不可或缺的无线和有线电视广播&#xff0c;几乎全部都采用调幅方式。其实&#xff0c;若是用调频方式来传输电视信号&#xff0c;…

Qt Quick - 分隔器综述

Qt Quick - 分隔器综述 一、概述二、MenuSeparator 控件1. 用法&#xff1a; 三、ToolSeparator 控件1. 用法 一、概述 Qt Quick Controls 提供了多种分隔符&#xff0c;其实就是分割一下MenuBar和ToolBar里面的内容。 控件功能MenuSeparator将菜单中的一组项目与相邻项目分开…

Spring Boot + Spring Security基础入门教程

Spring Security简介 Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。Spring Security 致力于为 Java 应用程序提供身份验证和授权的能力。 Spring Security 两大重要核心功能&#xff1a;用户认证&#xff08;Authentication&#xff09;和用户授权&am…

pandas 使用loc和iloc读取行数据或列数据

文章目录 一、 使用loc方法读取数据1.1 读取某行某列的值1.2 读取某个区域1.3 按照条件筛选 二. 使用iloc方法读取数据2.1 读取某行某列的值2.2 读取某个区域的数据 创建一个DataFrame data {name:[张三, 李四, 王五, 赵六],age:[20, 21, 22, 23], gender: [0, 1, 1, 1], stat…

网络工程项目报价单应该怎么写?记住这6个步骤准没错!

作为一名网络工程师&#xff0c;你在向潜在客户提供服务时&#xff0c;编写一个清晰明了的项目报价单是至关重要的。一个好的报价单不仅能够让客户更好地了解你的服务内容&#xff0c;还可以为你的项目提供更高的转化率。在本文中&#xff0c;我们将探讨如何编写一个有效的网络…

一图看懂 xlwt 模块:读写 Excel 文件的数据和格式信息, 资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 xlwt 模块&#xff1a;读写 Excel 文件的数据和格式信息, 资料整理笔记&#xff08;大全&#xff09; 摘要模块图类关系图模块全展开【xlwt】统计常量模块1 xlwt.compat2 x…