当前位置: 首页 > news >正文

【多线程】死锁 详解

死锁

  • 一. 死锁是什么
  • 二. 死锁的场景
    • 1. 一个线程一把锁
    • 2. 两个线程两把锁
    • 3. N 个线程 M 把锁
  • 三. 死锁产生的四个必要条件
  • 四. 如何避免死锁

一. 死锁是什么

死锁是这样一种情形:
多个线程同时被阻塞,因为每个进程都在等其他线程释放某些资源,同时又不释放自己占用的资源,从而导致系统陷入僵局。
由于线程被无限期地阻塞,因此程序不可能正常终止。
死锁是一种严重的 BUG!! 导致一个程序的线程 “卡死”, 无法正常工作!

二. 死锁的场景

1. 一个线程一把锁

一个线程对同一把锁上锁多次,如果该锁是 不可重入锁 就会死锁,否则是 可重入锁 就不会死锁。

代码举例:

        Object locker = new Object();// 对 locker 第一次加锁synchronized (locker) {// 对 locker 第二次加锁synchronized (locker) {// do something}}

因为 synchronized 是可重入锁, 所以它并不会导致死锁,但如果换成不可重入锁的话就会死锁。

2. 两个线程两把锁

A 持有 lock1, 等待 lock2, B 持有 lock2, 等待 lock1。
所以情况就是:
A 说:你先给我,我再给你。
B 说:我不,你先给我,我再给你。

比如:屋子的钥匙锁车里了,车钥匙锁屋里了。
代码举例:

class Test{public static void main(String[] args) throws InterruptedException {Object lock1 = new Object();Object lock2 = new Object();Thread threadA = new Thread(() -> {synchronized (lock1) {System.out.println("Thread A: Holding lock 1...");try { Thread.sleep(1000); } catch (InterruptedException e) {}System.out.println("Thread A: Waiting for lock 2...");synchronized (lock2) {System.out.println("Thread A: Acquired lock 2.");}}});Thread threadB = new Thread(() -> {synchronized (lock2) {System.out.println("Thread B: Holding lock 2...");try { Thread.sleep(1000); } catch (InterruptedException e) {}System.out.println("Thread B: Waiting for lock 1...");synchronized (lock1) {System.out.println("Thread B: Acquired lock 1.");}}});threadA.start();threadB.start();}
}

3. N 个线程 M 把锁

为了进一步阐述死锁的形成, 我们引用有名的 “哲学家就餐问题”.

  • 有个桌子, 围着一圈 哲学家, 桌子中间放着一盘意大利面. 每个哲学家两两之间, 放着一根筷子.

在这里插入图片描述

  • 每个哲学家只做两件事: 思考人生 或 吃面条. 思考人生时就会放下筷子. 吃面条就会拿起左右两边的筷子(先拿左边, 再拿右边).

  • 如果哲学家发现筷子拿不起来了(被别人占用了), 就会阻塞等待.

  • 假如出现极端情况:同一时刻, 五个 哲学家 同时拿起左手边的筷子, 然后再尝试拿右手的筷子, 就会发现右手的筷子都被占用了. 由于哲学家们互不相让, 这个时候就形成了 死锁.

在这里插入图片描述

三. 死锁产生的四个必要条件

  • 互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用。
  • 不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  • 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  • 环路等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

四. 如何避免死锁

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

其中最容易破坏的就是 “循环等待”.

最常用的一种死锁阻止技术就是锁排序:
假设有 N 个线程尝试获取 M 把锁, 就可以针对 M 把锁进行编号 (1, 2, 3…M).
N 个线程尝试获取锁的时候, 都按照固定的按编号由小到大顺序来获取锁. 这样就可以避免环路等待.

比如上面两个线程两把锁死锁的例子:

约定好先获取 lock1, 再获取 lock2 , 就不会环路等待.

class Test{public static void main(String[] args) throws InterruptedException {Object lock1 = new Object();Object lock2 = new Object();Thread threadA = new Thread(() -> {synchronized (lock1) {System.out.println("Thread A: Holding lock 1...");try { Thread.sleep(1000); } catch (InterruptedException e) {}System.out.println("Thread A: Waiting for lock 2...");synchronized (lock2) {System.out.println("Thread A: Acquired lock 2.");}}});Thread threadB = new Thread(() -> {synchronized (lock1) {System.out.println("Thread B: Holding lock 1...");try { Thread.sleep(1000); } catch (InterruptedException e) {}System.out.println("Thread B: Waiting for lock 2...");synchronized (lock2) {System.out.println("Thread B: Acquired lock 2.");}}});threadA.start();threadB.start();}
}

好啦! 以上就是对 死锁 的讲解,希望能帮到你 !
评论区欢迎指正 !

相关文章:

【多线程】死锁 详解

死锁 一. 死锁是什么二. 死锁的场景1. 一个线程一把锁2. 两个线程两把锁3. N 个线程 M 把锁 三. 死锁产生的四个必要条件四. 如何避免死锁 一. 死锁是什么 死锁是这样一种情形: 多个线程同时被阻塞,因为每个进程都在等其他线程释放某些资源,…...

成考[专升本政治]科目必背知识点

1. 马克思主义哲学研究的对象是:关于自然、社会、思维发展的一般规律。 2. 对待马克思主义的科学态度是:坚持和发展。 3. 物质的唯一特性是客观实在性。这里的客观实在是指:不以人的意志为转移。 4. 在实际工作中,要注意掌握…...

spring boot 使用AOP+自定义注解+反射实现操作日志记录修改前数据和修改后对比数据,并保存至日志表

一、添加aop starter依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>二&#xff1a;自定义字段翻译注解。&#xff08;修改功能时&#xff0c;需要显示如…...

【深度学习】Pytorch 系列教程(二):PyTorch数据结构:1、Tensor(张量): GPU加速(GPU Acceleration)

目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量&#xff08;Tensor&#xff09; 1. 维度&#xff08;Dimensions&#xff09; 2. 数据类型&#xff08;Data Types&#xff09; 3. GPU加速&#xff08;GPU Acceleration&#xff09; 一、前言 ChatGP…...

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构&#xff0c;它通过创建多个子进程来处理客户端连接&#xff0c;从而实现并发处理多个客户端请求的能力。 概念&#xff1a; 服务器启动时&#xff0c;创建主进程&#xff0c;并绑定监听端口。当有客户端连接请求…...

云计算——ACA学习 云计算分类

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 写在前面 前期回顾 本期介绍 一.云计算分类 1.公有云…...

3 分钟,带你了解低代码开发

一、低代码平台存在的意义 传统软件开发交付链中&#xff0c;需求经过3次传递&#xff0c;用户→业务→架构师→开发&#xff0c;每一层传递都可能使需求失真&#xff0c;导致最终交付的功能返工。 业务的变化促使软件开发过程不断更新、迭代和演进&#xff0c;而低代码开发即是…...

小白学Unity03-太空漫游游戏脚本,控制飞船移动旋转

首先搭建好太阳系以及飞机的场景 需要用到3个脚本 1.控制飞机移动旋转 2.控制摄像机LookAt朝向飞机和差值平滑跟踪飞机 3.控制各个星球自转以及围绕太阳旋转&#xff08;rotate()和RotateAround()&#xff09; 1.控制飞机移动旋转的脚本 using System.Collections; using…...

接口自动化测试推荐用什么框架?

在推荐接口自动化测试框架时&#xff0c;需要考虑多个因素&#xff0c;包括项目需求、技术栈、团队经验和个人偏好。 以下是几个常用的接口自动化测试框架供你参考&#xff1a; Postman&#xff1a; Postman是一个功能强大且易于上手的接口测试工具&#xff0c;它提供了许多…...

防火墙 FireWall

这里写自定义目录标题 一、概述二、防火墙分类三、防火墙性能四、硬件防火墙定义五、硬件防火墙作用&#xff08;拓扑图 ups&#xff09;六、硬件防火墙品牌七、软件防火墙八、iptables一、iptables是什么&#xff1f;二、netfilter/iptables功能三、iptables概念四、iptables中…...

【Linix-Day12-线程同步和线程安全】

线程同步 和 线程安全 线程同步 除了信号量和互斥锁&#xff08;互斥锁和条件变量上次介绍过&#xff09;&#xff0c;还有两种方式同步 1.读写锁 当同时对一块内存读写时&#xff0c;会出现下列问题&#xff0c;故而引入读写锁 接口介绍&#xff1a; 1.int pthread_rwloc…...

C++中使用嵌套循环遍历多维数组

C中使用嵌套循环遍历多维数组 一维数组&#xff1a;数组元素可以看做是一行数据。 二维数组&#xff1a;更像是一个表格&#xff0c;既有行数据又有列数据。 C没有提供二维数组类型&#xff0c;但用户可以创建每个元素本身都是数组的数组。例如&#xff0c;假设要存储 5 个城…...

linux入门---命名管道

如何创建命名管道 使用mkfifo函数就可以在程序里面创建管道文件&#xff0c;该函数的声明如下&#xff1a; 该函数需要两个参数&#xff0c;第一个参数表示要在哪个路径下创建管道文件并且这个路径得待上管道文件的名字&#xff0c;因为每个文件都有对应的权限&#xff0c;所…...

SpringBoot2.0入门(详细文档)

文章目录 Springboot是什么Springboot2.x依赖环境和版本新特性说明为什么学习Springboot从springboot优点来看从未来发展的趋势来看 开发环境Spring Boot开发环境搭建和项目启动jdk 的配置Spring Boot 工程的构建maven配置IDEA 快速构建maven 创建工程常用注解 完整代码 Spring…...

Aztec的隐私抽象:在尊重EVM合约开发习惯的情况下实现智能合约隐私

1. 引言 Aztec的架构&#xff0c;不同于当前“通过EVM兼容执行环境”所实现的区块链水平扩容趋势。Aztec内部笑称其构建的为首个非zkEVM协议。 Aztec专注于实现&#xff1a; 成为理解和需要智能合约隐私的开发者的终极解决方案。 Aztec为开发者提供构建隐私优先app所需的网…...

【Vue】详细介绍Vue项目的目录结构及各个核心文件的示例代码

Vue.js并没有严格的文件和目录结构要求&#xff0c;但一般情况下&#xff0c;我们的Vue项目目录结构如下&#xff1a; ├── node_modules/ # 项目依赖的 node 模块 ├── public/ # 公共资源目录 │ ├── favicon.ico # 网页图标 │ └──…...

【人大金仓】迁移MySql数据库到人大金仓,出现sys_config表重复

需要迁移的数据库中有张表名称为sys_config&#xff0c;查询的时候查询结果不符合我们的预期&#xff0c;经咨询金仓售后人员后得知和系统表重名… 解决问题方法如下&#xff1a; alter database [数据库名] set search_path to "$user", [模式名,&#xff08;可选&…...

linux内核进程间通信IPC----消息队列

消息队列&#xff1a;提供一种从一个进程向另一个进程发送一个数据块的方法。与FIFO相比&#xff0c;消息队列的优势在于&#xff0c;它独立于发送和接收进程而存在。 1.链表式结构组织&#xff0c;存放于内核。 2.通过队列标识来引用。 3.通过一个数据类型来索引指定的数据。 …...

PHP实现微信小程序状态检测(违规、暂停服务、维护中、正在修复)

实现原理 进入那些状态不正常的小程序会被重定向至一个Url&#xff0c;使用抓包软件抓取这个Url&#xff0c;剔除不必要参数&#xff0c;使用cURl函数请求网页获得HTML内容&#xff0c;根据内容解析出当前APPID的小程序的状态。 代码 <?php// 编码header(Content-type:ap…...

ubuntu在线直接升级

前几天VMware上安装了ubuntu&#xff0c;当时的内核版本支持(ipguard,加密软件)&#xff0c;后来ubuntu自动升级了linux内核&#xff0c;导致加入软件不支持&#xff0c;无法访问加密文件了。后来加密软件商更新了软件&#xff0c;但还是赶不上linux内核更新速度&#xff0c;还…...

springboot网络小说在线阅读网站的设计与实现

目录需求分析技术选型数据库设计核心功能实现性能优化安全防护测试部署项目技术支持源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作需求分析 明确网站的核心功能和用户需求。网络小说在线阅读网站通常需要包含以下功能模块&#xff1a;用户…...

手把手教你用Hive SQL搞定电影评分数据分析(附完整数据集和避坑指南)

手把手教你用Hive SQL搞定电影评分数据分析&#xff08;附完整数据集和避坑指南&#xff09; "为什么《肖申克的救赎》常年霸占IMDb Top 250榜首&#xff1f;"这个问题背后隐藏着海量用户评分数据的秘密。作为数据分析师&#xff0c;我们如何从原始评分数据中挖掘出这…...

MATLAB中扩展卡尔曼滤波与无迹卡尔曼滤波源代码:一键运行,误差对比及显示最大误差数字图像程...

MATLAB编写的EKF和UKF滤波程序源代码 扩展卡尔曼滤波、无迹卡尔曼滤波的MATLAB程序&#xff0c;有误差对比图像和最大误差数字的显示。 只有一个m文件&#xff0c;打开就能运行。 带中文注释。直接双击EKFUKFComparison.m就能看到两个滤波器在非线性系统里的较量。这个文件里塞…...

统信UOS 1060e内网离线安装Docker保姆级教程(附CentOS 8 RPM包下载)

统信UOS 1060e内网离线安装Docker全流程实战指南 在企业级IT基础设施中&#xff0c;内网环境下的软件部署一直是运维工程师面临的特殊挑战。当服务器完全隔离于互联网时&#xff0c;每一个依赖包、每一条配置指令都可能成为阻碍系统正常运行的潜在障碍。本文将深入探讨在统信UO…...

3个步骤玩转虚拟手柄模拟:ViGEmBus驱动从入门到精通

3个步骤玩转虚拟手柄模拟&#xff1a;ViGEmBus驱动从入门到精通 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus Windows虚拟手柄驱动技术为游戏玩家和开发者…...

给CUDA新手的3DGS代码导读:从forward.cu到backward.cu,一步步拆解渲染流程

给CUDA新手的3DGS代码导读&#xff1a;从forward.cu到backward.cu&#xff0c;一步步拆解渲染流程 第一次看到3D Gaussian Splatting&#xff08;3DGS&#xff09;的CUDA代码时&#xff0c;我盯着那些复杂的核函数和内存操作发了半小时呆。作为从PyTorch转型过来的研究者&#…...

IT 流程越来越完整,但管理反而变得更难了

在很多企业的 IT 管理过程中&#xff0c;一个非常明显的趋势是&#xff1a;流程在不断增加。 从最初的简单问题处理&#xff0c;到后来的事件管理、问题管理、变更管理&#xff0c;再到审批流程、发布流程&#xff0c;各类流程逐渐被建立起来。从管理角度看&#xff0c;这是一种…...

Nexus | 连接预测和决策:数据驱动优化的进展和挑战

文章信息论文题目为《Bridging prediction and decision: Advancesand challenges in data-driven optimization》&#xff0c;该文于2025年发表于《Nexus》期刊上。摘要数据驱动方法通过将预测与决策相结合&#xff0c;彻底改变了传统的优化方法。文章探讨了三种关键方法 ——…...

【架构实战】架构师成长路线图

一、架构师的核心能力 架构师不是只会画图的技术人&#xff0c;而是能在技术、业务、团队之间找到平衡点的综合型人才。 技术深度 精通至少一个技术领域理解底层原理&#xff0c;不浮于表面持续跟踪新技术趋势 系统思维 全局视角看问题懂得权衡&#xff08;Trade-off&#xff0…...

为什么你的MoveIt2 Python API总报错?ROS2环境变量与PYTHONPATH的隐藏陷阱

为什么你的MoveIt2 Python API总报错&#xff1f;ROS2环境变量与PYTHONPATH的隐藏陷阱 当你第一次在ROS2中尝试使用MoveIt2的Python API时&#xff0c;那种"ModuleNotFoundError: No module named moveit"的报错信息可能会让你抓狂。这不是因为你做错了什么&#xff…...