死锁(JAVA)

死锁在多线程代码中是非常严重的BUG,一旦代码中出现死锁就会导致线程卡死。
单个线程连续两次同一个对象进行加锁操作时,如果该锁是不可重入锁就会发生死锁(线程卡死)

两个线程两把锁,如果出现这种情况也是会发生死锁:线程t1已经获取了锁A,线程t2已经获取了锁B,此时t1想要获取锁B,t2想要获取锁A。

Object lock1 = new Object();
Object lock2 = new Object();
 
Thread t1 = new Thread(()->{
    synchronized(lock1) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized(lock2) {
 
        }
    }
});
Thread t2 = new Thread(()->{
    synchronized(lock2) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        synchronized(lock1) {
 
        }
    }
});
t1.start();
t2.start();
//让主线程等待 2 秒
Thread.sleep(2000);
//此时t1和t2两个线程会因为互相争对方的锁,而导致死锁
System.out.println(t1.getState());
System.out.println(t2.getState());

在这里插入图片描述

如果此时有N个线程M把锁(N,M>>2),就更加容易发生死锁的情况了。

一个非常经典的N个线程M把锁的问题:哲学家就餐问题。

假设有5名哲学家围在一张桌子上吃面,现在桌子上有5根筷子。(哲学家会做两件事:思考和吃面(吃面必须要拿到两根筷子,吃完后会将筷子放回原处)。且做这两件事的时间是完全随机的,同一时间只能做一件事)
在这里插入图片描述
大多数情况下是不会出现问题的但也会出现一些极端情况:现在所有的哲学家都想吃面,他们同时拿起了自己左手边的筷子,此时每位哲学家手里都有且仅有一只筷子,此时每位哲学家都在等待另一支筷子就会发生死锁。
那么该如何解决死锁问题呢?首先我们先要了解死锁的必要条件,然后根据这些条件来修改。

引发死锁的必要条件

  1. 互斥(锁的基本特性);当一个线程获取到锁后,如果另一个线程也想获取该锁就会阻塞等待。
  2. 不可抢占(锁的基本特性);当线程A获取到锁后,如果线程B也想获取该锁只能等待A将该锁释放后再获取,不能直接抢。
  3. 请求保持(代码结构);一个线程获取了A锁后继续获取B锁……且前面获取的锁不进行释放。
  4. 循环等待/环路等待(代码结构);等待的依赖关系形成了环。

一个死锁代码一定会满足上述四种情况,任意一个不满足都不会形成死锁。

死锁的解决方法

解决死锁的情况只要破坏上述条件中的任意一个就行了。
上述四条中1和2都是锁的基本特性,所以无法改变。
对于3,在代码中尽量避免出现锁嵌套的情况,但是这种情况很难避免,因为实际代码中的嵌套往往都是这样的,很难发现和避免:

public void fun1(){
    synchronized (this) {
        fun2();
    }
}
public void fun2(){
    fun3();
}
public void fun3(){
    fun4();
}
public void fun4(){
    synchronized (this) {
    }
}

所以解决4就显得非常重要了,那么4这种情况该如何避免呢?
有一个非常简单的方法那就是约定加锁的顺序。
例如对于上文中的哲学家就餐的问题:
现在给每支筷子进行编号,约定每位哲学家拿筷子的顺序都是必须先拿面前编号较小的然后再拿编号较大的。
在这里插入图片描述
B拿1号筷子->C拿2号筷子->D拿3号筷子->E拿4号筷子->A拿1号筷子但是1号筷子此时在B手中所以A会阻塞等待,此时E拿到5号筷子吃完后放下筷子->D拿到4号筷子吃完后放下筷子->C拿到3号筷子吃完后放下筷子->B拿到2号筷子吃完后放下筷子。
此时就完美避免了死锁问题的发生。

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

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

相关文章

基于Python+Django的寻人失物失物招领系统

运行环境 开发语言:Python python框架:django 软件版本:python3.7 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:PyCharm/vscode 前端框架:vue.js 项目介绍 寻人失物失物招领系统交流平台的主要使用…

尝试使用php给pdf添加水印

在开发中增加pdf水印的功能是很常见的,经过实验发现这中间还是会有很多问题的。第一种模式,采用生成图片的方式把需要添加的内容保存成图片,再将图片加到pdf中间,这种方法略麻烦一些,不过可以解决中文乱码的问题&#…

pip如何切换至国内镜像

目录 前言一、pip介绍二、超时问题三、切换至国内镜像源1.操作环境2.切换国内镜像 四、国内pip镜像源总结 前言 大家好,我是🐌蜗牛老师。今天讲在 Python 编程学习或开发中遇到的一个小问题,又是我们经常会遇到的一个问题。那就是切换镜像&a…

一文带你深入浅出Web的自动化测试工具Selenium【建议收藏】

文章目录 前言第01节 Selenium概述第02节 安装浏览器驱动(以Google为例)第03节 定位页面元素1. 打开指定页面2. id 定位3. name 定位4. class 定位5. tag 定位6. xpath 定位7. css 选择器8. link 定位9. 示例 有道翻译 第04节 浏览器控制1. 修改浏览器窗…

CTFhub-RCE-读取源代码

源代码&#xff1a; <?php error_reporting(E_ALL); if (isset($_GET[file])) { if ( substr($_GET["file"], 0, 6) "php://" ) { include($_GET["file"]); } else { echo "Hacker!!!"; } } else {…

DALLE 2 文生图模型实践指南

前言&#xff1a;最近在运行dalle2模型进行推断&#xff0c;本篇博客记录相关资料。 相关博客&#xff1a;超详细&#xff01;DALL E 文生图模型实践指南 目录 1. 环境搭建和预训练模型准备环境搭建预训练模型下载 2. 代码3. BUG&DEBUGURLErrorRuntimeErrorCUDA error 1. …

基于鸡群算法优化概率神经网络PNN的分类预测 - 附代码

基于鸡群算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于鸡群算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于鸡群优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

Python高级语法----Python多线程与多进程

文章目录 多线程多进程注意事项多线程与多进程是提高程序性能的两种常见方法。在深入代码之前,让我们先用一个简单的比喻来理解它们。 想象你在一家餐厅里工作。如果你是一个服务员,同时负责多个桌子的顾客,这就类似于“多线程”——同一个人(程序)同时进行多项任务(线程…

在虚拟环境下安装python包

PyCharm可以自己给项目创建虚拟环境&#xff0c;示例如下&#xff1a; 首先通过File—>Setting—>Project&#xff1a;【项目名称】—>Project Interpreter—>设置—>add—>Virtuallenv Environment配置虚拟环境即可 添加解释器&#xff1a; 当创建虚拟环…

Android Glide transform圆形图CircleCrop动态代码描边绘制外框线并rotateImage旋转,Kotlin

Android Glide transform圆形图CircleCrop动态代码描边绘制外框线并rotateImage旋转&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app&q…

【每日一题】区域和检索 - 数组可修改

文章目录 Tag题目来源解题思路方法一&#xff1a;分块方法二&#xff1a;线段树方法三&#xff1a;树状数组 写在最后 Tag 【树状数组】【线段树】【分块】【前缀和】【设计类】【2023-11-13】 题目来源 307. 区域和检索 - 数组可修改 解题思路 使用前缀和解决不行吗&#x…

laravel日期字段carbon 输出格式转换

/*** The attributes that should be cast.** var array*/ protected $casts [created_at > datetime:Y-m-d, ]; 滑动验证页面https://segmentfault.com/q/1010000043327049

es性能强悍的推演过程

前言 es底层复用的Lucene的能力&#xff0c;Lucene在以前的文章中有所讲解&#xff0c;感兴趣可查看 https://blog.csdn.net/u013978512/article/details/125474873?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169771769916777224433628%2522%252C%2522scm%2522…

4、创建第一个鸿蒙应用

一、创建项目 此处以空模板为例来创建一个鸿蒙应用。在创建项目前请保持网页的畅通。 1、在欢迎页面点击“Create Project”。 2、左侧默认为“Application”&#xff0c;在“Template Market”中选择空模板&#xff08;Empty Ability&#xff09;&#xff0c;点击“Next” 3…

【优化版】DOSBox及常用汇编工具的详细安装教程

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、图解数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. dosbox的介绍、下载和安装1.1 dosbos简介1.2 dosbox的下载1.2.1 方式一&a…

APP备案获取安卓app证书公钥获取方法和签名MD5值

前言 在开发和发布安卓应用程序时&#xff0c;了解应用程序证书的公钥和签名MD5值是很重要的。这些信息对于应用程序的安全性和合规性至关重要。现在又因为今年开始APP必须接入备案才能在国内各大应用市场上架&#xff0c;所以获取这两个值成了所有开发者的必经之路。本文将介…

关于论文图表目录和交叉引用的使用小结

目录 1 题注用法 2 交叉引用 最近在写论文&#xff0c;遇到不少Word使用的问题(错误&#xff01;文档中没有指定样式的文字。) 网上其实也有很多解决方案但我当时还是折腾了几个小时才整出来图目录&#xff0c;以下是针对我目前使用的感觉简明很多的方法。 1 题注用法 1) 假…

4.2每日一题(求多元函数在某一点的微分)

1、分别求x和y的偏导&#xff0c;再相加即可 2、因为多元函数的表达式不方便求偏导&#xff0c;所以可以使用先代后求法&#xff1a; &#xff08;1&#xff09;对x偏导&#xff1a;把y0代入&#xff0c;很容易求出对x偏导的结果 &#xff08;2&#xff09;对y偏导&#xff1a…

《QT从基础到进阶·二十五》界面假死处理

假如有这样一种情况&#xff0c;我们在主线程写了一个死循环&#xff0c;当程序运行到主线程的死循环代码后界面便卡死点了没有反应&#xff0c;这里提供几种方法处理界面假死的情况&#xff0c;保证比如主线程在执行死循环没有退出的时候点击界面不会卡死能继续执行其他功能。…

nmap原理与使用

kali的命令行中可以直接使用 nmap 命令&#xff0c;打开一个「终端」&#xff0c;输入 nmap 后回车&#xff0c;可以看到 nmap 的版本&#xff0c;证明 nmap 可用。 一、端口扫描 扫描主机的「开放端口」&#xff0c;在nmap后面直接跟主机IP&#xff08;默认扫描1000个端口&am…
最新文章