【JavaEE初阶】 死锁详解

文章目录

  • 🎋死锁的概念
  • 🌳死锁的三个典型情况
    • 🚩一个线程一把锁
    • 🚩两个线程两把锁
    • 🚩n个线程m把锁(哲学家就餐问题)
  • 🎄如何破除死锁
    • 🚩破坏循环等待

本文重点:

  • 死锁咋回事

  • 死锁的三个典型情况

  • 死锁的四个必要条件

  • 如何破除死锁

🎋死锁的概念

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。此时就发生了死锁

🌳死锁的三个典型情况

🚩一个线程一把锁

一个线程一把锁,但是都是不可重入锁。该线程争对这个锁连续加锁就会陷入死锁

在这里插入图片描述

什么叫不可重入锁呢?为什么不可重入锁会造成死锁呢?

一个线程没有释放锁, 然后又尝试再次加锁

  • 按照之前对于锁的设定, 第二次加锁的时候, 就会阻塞等待.

  • 直到第一次的锁被释放, 才能获取到第二个锁.

  • 但是释放第一个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想干了, 也就无法进行解锁操作.

  • 这时候就会死锁

举个例子:

一个滑稽老铁去上厕所,反锁厕所们后,然后不小心一个闪现出来了,还失忆了,这时候厕所没人,但是处于锁的状态,后面等待的人无法进入
在这里插入图片描述
这样的锁称为不可重入锁

值得注意的是:Java 中的synchronized是可重入锁, 因此没有上面锁死的问题

🚩两个线程两把锁

两个线程两把锁,把这两个线程先分别获取一把锁,然后再同时尝试获取对方的锁。
在这里插入图片描述
举个例子:

阿强和阿珍一起去饺子馆吃饺子.
阿强点了一份汤,阿珍点了一份饺子
这时候他们都想尝尝对方的东西,这时候就有
阿强说:你先给我吃饺子,我再给你喝汤
阿珍说:你先给我和汤,我再给你吃饺子
如果这俩人彼此之间互不相让, 就构成了死锁.
饺子和汤相当于是两把锁, 这两个人就是两个线程

在这里插入图片描述
这时候阿珍和阿强就会发生僵持,发生死锁

接下来我我们写个程序来模拟一下

代码如下:

public class EatLock {public static void main(String[] args) {Object soup = new Object();Object dumplings = new Object();Thread thread1 = new Thread(()->{synchronized (soup) {//等待是为了让另一个线程有时间给第一层加锁try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (dumplings) {System.out.println("阿珍喝到了汤,也吃到了饺子");}}},"阿珍");thread1.start();Thread thread2 = new Thread(()->{synchronized (dumplings) {//等待是为了让另一个线程有时间给第一层加锁try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (soup) {System.out.println("阿强吃到了饺子,也喝到了汤");}}},"阿强");thread2.start();}
}

代码结果就是堵塞,这里就不展示了

这里我们通过jconsole命令来进行查看一下各个线程的状态,不会使用的读者可以到博主写的《【JavaEE初阶】线程的概念与创建》里面学习详细的查看方法,这里就不做过多赘述了

在这里插入图片描述
在这里插入图片描述
这里我们可以看到阿强与阿珍都处于等待状态

🚩n个线程m把锁(哲学家就餐问题)

问题是这样的:

  • 有个桌子, 围着一圈 哲 学 家, 桌子中间放着一盘意大利面. 每个哲学家两两之间, 放着一根筷子
    在这里插入图片描述
  • 每个 哲 学 家 只做两件事: 思考人生 或者 吃面条. 思考人生的时候就会放下筷子. 吃面条就会拿起左
    右两边的筷子(先拿起左边, 再拿起右边)
    在这里插入图片描述
  • 如果 哲 学 家 发现筷子拿不起来了(被别人占用了), 就会阻塞等待.

在这里插入图片描述

  • [关键点在这] 假设同一时刻, 五个 哲 ♂ 家 同时拿起左手边的筷子, 然后再尝试拿右手的筷子, 就会发现右手的筷子都被占用了. 由于 哲 ♂ 家 们互不相让, 这个时候就形成了 死锁

在这里插入图片描述
死锁是一种严重的 BUG!! 导致一个程序的线程 “卡死”, 无法正常工作

🎄如何破除死锁

想要破除死锁,首先的弄懂java死锁的四个必要条件

java 死锁产生的四个必要条件:

  1. 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

  2. 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

  3. 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。

  4. 循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

由于前三个条件是操作系统的特性,所以我们无法改变,我们能做其中最容易破坏的就是 “循环等待”.

🚩破坏循环等待

最常用的一种死锁阻止技术就是锁排序. 假设有 N 个线程尝试获取 M 把锁, 就可以针对 M 把锁进行编号
(1, 2, 3…M).

N 个线程尝试获取锁的时候, 都按照固定的按编号由小到大顺序来获取锁. 这样就可以避免环路等待.

比如我们上述阿强与阿珍吃饭的例子

就是因为两个线程对于加锁的顺序没有约定, 就容易产生环路等待

解决方法:

我们预定好先给阿珍喝汤,再给阿强吃饺子,这样就不会产生死锁了,修改代码如下:

public class EatLock {public static void main(String[] args) {Object soup = new Object();Object dumplings = new Object();Thread thread1 = new Thread(()->{synchronized (soup) {//等待是为了让另一个线程有时间给第一层加锁try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (dumplings) {System.out.println("阿珍喝到了汤,也吃到了饺子");}}},"阿珍");thread1.start();Thread thread2 = new Thread(()->{synchronized (soup) {//等待是为了让另一个线程有时间给第一层加锁try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (dumplings) {System.out.println("阿强吃到了饺子,也喝到了汤");}}},"阿强");thread2.start();}
}

运行结果如下:
在这里插入图片描述
哲学家问题也同理,这里就不做过多赘述了

⭕总结
关于《【JavaEE初阶】 死锁》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SkyWalking】SkyWalking是如何实现跨进程传播链路数据?

文章目录 一、简介1 为什么写这篇文章2 跨进程传播协议-简介 二、协议1 Standard Header项2 Extension Header项3 Correlation Header项 三、跨进程传播协议的源码分析1 OpenTracing规范2 通过dubbo插件分析跨进程数据传播3 分析跨进程传播协议的核心源码 四、小结参考 一、简介…

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升,测评补单成为了商家们提升销售和用户口碑的关键环节。然而,如何在保持成本低廉的同时确保操作安全,一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略,帮助卖家们产品的…

嵌入式C语言自我修养《内存堆栈管理》学习笔记

目录 一、Linux环境下的内存管理 二、栈的管理 三、堆内存管理 四、mmap映射区 五、内存泄漏与防范 六、常见的内存错误及检测 C程序中定义的函数、全局变量、静态变量经过编译链接后,分别以section的形式存储在可执行文件的代码段、数据段和BSS段中。当程序运…

【Zabbix】Zabbix学习笔记

现在Zabbix Server存在的问题: 问题1: Zabbix server: Utilization of discoverer processes over 75% 问题2: Zabbix server: Utilization of icmp pinger processes over 75% 优化的解决办法是修改配置文件把Discovery和Pinger进程数量调大…

04-RocketMQ源码解读

目录汇总:RocketMQ从入门到精通汇总 上一篇:03-RocketMQ高级原理 这一部分,我们开始深入RocketMQ的源码。源码的解读是个非常困难的过程,每个人的理解程度都会不一样,也不太可能通过讲解把其中的细节全部讲明白。我们今…

panads操作excel

panads简介 pandas是基于Numpy创建的Python包,内置了大量标准函数,能够高效地解决数据分析数据处理和分析任务,pandas支持多种文件的操作,比如Excel,csv,json,txt 文件等,读取文件之…

unity发布微信小游戏,未找到 game.json报错原因

unity发布微信小游戏,未找到 game.json报错原因 同一个问题相隔一年遇到两次,两次原因都不一样,记录一下,以后不要再掉坑里 原因一:申请的appID是小程序不是小游戏 解决方法:需要在程序平台修改服务类目 如…

哈希应用之布隆过滤器

文章目录 1.介绍1.1百度搜索1.2知乎好文1.3自身理解 2.模拟实现2.1文档阅读2.2代码剖析 3.误判率的研究4.布隆过滤器的应用4.1如何找到两个分别有100亿个字符串的文件的交集[只有1G内存].分别给出精确算法和近似算法4.2如何扩展BloomFilter使得它支持删除元素的操作 5.整体代码…

pytorch中nn.DataParallel多次使用

pytorch中nn.DataParallel多次使用 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader# 定义模型 class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.fc nn.Linear(10, 1)def forwa…

ROS为机器人装配激光雷达

移动机器人在环境中获取障碍物的具体位置、房间的内部轮廓等信息都是非常必要的,这些信息是机器人创建地图、进行导航的基础数据,除上面所讲的Kinect,还可以使用激光雷达作为这种场景应用下的传感器。 激光雷达可用于测量机器人和其他物体之间…

3.简单场景构建

在新建的项目中,默认存在 Main Camera 和 Directional Light两个对象。若是缺失,可通过选择菜单中的 Game Object->Camera 和 Geme Object->Light->Directional Light进行创建。 1.添加地形及底图 通过在Cesium面板中选择 Cesium World Terrai…

批量文件重命名软件 A Better Finder Rename 11汉化for mac

A Better Finder Rename 11是一款功能强大的文件重命名工具,可在Mac操作系统上使用。它提供了简单而直观的界面,帮助用户快速批量重命名文件和文件夹,提高文件管理和组织效率。 以下是A Better Finder Rename 11可能提供的一些主要功能和特点…

设计模式 - 结构型模式考点篇:适配器模式(类适配器、对象适配器、接口适配器)

目录 一、适配器模式 一句话概括结构式模式 1.1、适配器模式概述 1.2、案例 1.2.1、类适配器模式实现案例 1.2.2、对象适配器 1.2.3、接口适配器 1.3、优缺点(对象适配器模式) 1.4、应用场景 一、适配器模式 一句话概括结构式模式 教你将类和对…

多线程入门

1 创建线程 下面的程序&#xff0c;我们可以用它来创建一个 POSIX 线程&#xff1a; #include <pthread.h> pthread_create (myThread, attr, start_routine, arg) 在这里&#xff0c;pthread_create 创建一个新的线程&#xff0c;并让它可执行。下面是关于参数的说明…

QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样 Chapter1 QT自制软键盘 最完美、最简单、跟自带虚拟键盘一样一、本自制虚拟键盘特点二、windows打开系统自带软键盘三、让…

3、在docker 容器中安装tomcat

&#xff11;、在服务器上查找tomcat镜像,查看前5条 docker search tomcat --limit 5​​​​​​​ 2、拉取镜像到本地 拉取官方的tomcat到本地 docker pull tomcat:9.0.34-jdk8 3、查看本地镜像 docker images |grep tomcat 4、启动tomcat 服务 使用默认配置 docker ru…

如何选择一个向量数据库:Elastic Cloud 和 Zilliz Cloud 面面观

随着以 Milvus 为代表的向量数据库在 AI 产业界越来越受欢迎&#xff0c;诸如 Elasticsearch 之类的传统数据库和检索系统也开始行动起来&#xff0c;纷纷在快速集成专门的向量检索插件方面展开角逐。 例如&#xff0c;在提供类似插件的传统数据库中&#xff0c;Elasticsearch …

VAE模型(详细推导+实例代码)

文章目录 EM算法思路E步M步直观感觉 GMM模型VAEVAE思想从GMM到VAE公式推导重参数VAE神经网络另一个视角的VAE思想为什么引入encoder为什么要重参数噪声与重建 Discrete VAE 本文会从EM算法&#xff0c;GMM模型一步一步的的推导&#xff0c;在过渡到VAE模型&#xff0c;如果有熟…

棱镜七彩参编!开源领域4项团体标准正式发布

近日&#xff0c;中电标2023年第27号团体标准公告正式发布&#xff0c;《T/CESA 1270.2-2023 信息技术 开源治理 第 2 部分&#xff1a;企业治理评估模型》、《T/CESA 1270.3-2023 信息技术 开源治理 第 3 部分&#xff1a;社区治理框架》、《T/CESA 1270.5-2023 信息技术 开源…

信创办公–基于WPS的EXCEL最佳实践系列 (单元格与行列)

信创办公–基于WPS的EXCEL最佳实践系列 &#xff08;单元格与行列&#xff09; 目录 应用背景操作步骤1、插入和删除行和列2、合并单元格3、调整行高与列宽4、隐藏行与列5、修改单元格对齐和缩进6、更改字体7、使用格式刷8、设置单元格内的文本自动换行9、应用单元格样式10、插…