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

死锁Deadlock

定义

        死锁是指两个或多个线程互相持有对方所需的资源,从而导致它们无法继续执行的情况。如下图所示,现有两个线程,分别是线程A及线程B,线程A持有锁A,线程B持有锁B。此时线程A想获取锁B,但锁B需等到线程B的结束才能解锁;而线程B想获取锁A,但锁A需等到线程A的结束才能解锁,这样就造成了线程A等线程B,线程B等线程A,从而出现死锁。

图解两线程死锁现象

c++死锁示例 

#include <iostream>
#include <thread>
#include <mutex>std::mutex mutexA;
std::mutex mutexB;void ThreadA()
{std::unique_lock<std::mutex> lockA(mutexA);std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 为了增加发生死锁的概率,让线程A先获取锁A再休眠一段时间std::cout << "Thread A acquired mutex A" << std::endl;std::unique_lock<std::mutex> lockB(mutexB);std::cout << "Thread A acquired mutex B" << std::endl;// 执行操作...lockB.unlock();lockA.unlock();
}void ThreadB()
{std::unique_lock<std::mutex> lockB(mutexB);std::cout << "Thread B acquired mutex B" << std::endl;std::unique_lock<std::mutex> lockA(mutexA);std::cout << "Thread B acquired mutex A" << std::endl;// 执行操作...lockA.unlock();lockB.unlock();
}int main()
{std::thread threadA(ThreadA);std::thread threadB(ThreadB);threadA.join();threadB.join();return 0;
}

输出结果:(程序中止崩溃)

分析: 

        在上述代码中,有两个线程(ThreadA和ThreadB),它们都试图以不同的顺序获取两个互斥锁(mutexA和mutexB)。如果ThreadA先获取了mutexA,然后尝试获取mutexB,而ThreadB先获取了mutexB,然后尝试获取mutexA,那么就会发生死锁。

        当ThreadA获取了mutexA后,它会休眠一段时间。在此期间,ThreadB获取了mutexB。接着,ThreadA试图获取mutexB时会被阻塞,因为ThreadB持有mutexB。同时,ThreadB也试图获取mutexA时会被阻塞,因为ThreadA持有mutexA。这样,两个线程都无法继续执行,导致程序陷入死锁状态。

        需要注意的是,死锁不一定会在每次运行时都发生,它取决于线程的调度和执行顺序。如果在实际应用中遇到死锁问题,可以通过合理的锁顺序、避免嵌套锁、使用死锁检测等方法来预防和解决死锁。

c++解决死锁

修改上述代码,使用std::lock函数来避免死锁:

#include <iostream>
#include <thread>
#include <mutex>std::mutex mutexA;
std::mutex mutexB;void ThreadA()
{std::unique_lock<std::mutex> lockA(mutexA, std::defer_lock);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::cout << "Thread A acquired mutex A" << std::endl;std::unique_lock<std::mutex> lockB(mutexB, std::defer_lock);std::cout << "Thread A acquired mutex B" << std::endl;std::lock(lockA, lockB);  // 使用std::lock同时获取两个锁// 执行操作...lockB.unlock();lockA.unlock();
}void ThreadB()
{std::unique_lock<std::mutex> lockB(mutexB, std::defer_lock);std::cout << "Thread B acquired mutex B" << std::endl;std::unique_lock<std::mutex> lockA(mutexA, std::defer_lock);std::cout << "Thread B acquired mutex A" << std::endl;std::lock(lockA, lockB);  // 使用std::lock同时获取两个锁// 执行操作...lockA.unlock();lockB.unlock();
}int main()
{std::thread threadA(ThreadA);std::thread threadB(ThreadB);threadA.join();threadB.join();return 0;
}

输出结果:(正确结果)

分析:

        在修改后的代码中,使用std::defer_lock参数来延迟锁的获取,而不是在构造std::unique_lock对象时立即获取锁。然后,在需要同时获取两个锁的地方,使用std::lock函数来获取锁,这样可以避免死锁发生。

        需要注意的是,虽然上述方法可以解决死锁问题,但在实际编程中,应尽量避免复杂的锁依赖关系和嵌套锁的使用,以减少死锁的可能性。

产生死锁的原因

竞争不可抢占资源(互斥资源)
线程推进顺序不当

产生死锁的四个必要条件

  1. 互斥条件(Mutual Exclusion):至少有一个资源同时只能被一个进程或线程占用,即在一段时间内只能有一个进程或线程访问该资源。

  2. 请求与保持条件(Hold and Wait):进程或线程在持有至少一个资源的同时,又请求其他进程或线程所持有的资源。

  3. 不可剥夺条件(No Preemption):已经分配给一个进程或线程的资源不能被强制性地剥夺,只能由持有资源的进程或线程显式地释放。

  4. 循环等待条件(Circular Wait):存在一个进程或线程的资源请求序列,使得每个进程或线程都在等待下一个进程或线程所持有的资源。

当这四个条件同时满足时,就可能发生死锁。

例如,考虑以下场景:

  • 进程A持有资源X,并请求资源Y。
  • 进程B持有资源Y,并请求资源X。

        如果进程A和进程B同时运行,并且它们按照上述顺序获取和释放资源,那么就会出现死锁。进程A持有资源X,进程B持有资源Y,但它们互相需要对方持有的资源才能继续执行,导致两个进程都无法继续执行下去。

处理死锁的方法

(1)预防死锁(破坏四条件)

  1. 破坏互斥条件:例如,对于某些资源,引入共享访问的机制,使得多个进程或线程可以同时访问资源。

  2. 破坏请求与保持条件:要求进程在请求资源之前释放已经持有的资源,或者一次性请求所有需要的资源。

  3. 破坏不可剥夺条件:引入资源预约和强制剥夺机制,以确保资源可以被其他进程或线程使用。

  4. 破坏循环等待条件:通过定义资源的线性顺序,要求进程按照相同的顺序请求资源,从而避免循环等待。

(2)避免死锁(银行家算法)

 

相关文章:

死锁Deadlock

定义 死锁是指两个或多个线程互相持有对方所需的资源&#xff0c;从而导致它们无法继续执行的情况。如下图所示&#xff0c;现有两个线程&#xff0c;分别是线程A及线程B&#xff0c;线程A持有锁A&#xff0c;线程B持有锁B。此时线程A想获取锁B&#xff0c;但锁B需等到线程B的结…...

【spark客户端】Spark SQL CLI详解:怎么执行sql文件、注释怎么写,支持的文件路径协议、交互式模式使用细节

文章目录 一. Spark SQL Command Line Options(命令行参数)二. The hiverc File1. without the -i2. .hiverc 介绍 三. 支持的路径协议四. 支持的注释类型五. Spark SQL CLI交互式命令六. Examples1. running a query from the command line2. setting Hive configuration vari…...

虹科干货 | HK-TrueNAS版本大揭秘!一文教您如何选择合适的TrueNAS软件

文章来源&#xff1a;虹科网络基础设施 阅读原文&#xff1a;https://mp.weixin.qq.com/s/Iv0zDDmiDgE9vEGlAZs-sg 1&#xff0e;导语 TrueNAS是虹科iXsystems 设计和开发的NAS 操作系统&#xff0c;提供许多功能&#xff0c;例如文件存储、虚拟机 (VM) 和媒体服务器。它基于…...

前端html+css+js实现的2048小游戏,很完善。

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 逻辑用的是JavaScript&#xff0c;界面用canvas实现&#xff0c;暂时还没有添加动画。 视频浏览地址...

学习通签到

要在Vue中使用H5lock.js&#xff0c;首先需要将H5lock.js引入到项目中。可以通过以下步骤来使用&#xff1a; 1. 将H5lock.js文件保存到项目中的某个目录下&#xff0c;例如src/assets文件夹。 2. 在需要使用H5lock.js的组件中&#xff0c;通过import语句将H5lock.js引入进来…...

target采退、测评养号购物下单操作教程

1.点击右上角的Create account注册账号 2.填写账号信息 3. 进入自己需要购买的商品页面 点击pick it up购买 4. 进入购物车页面选择快递方式和地址后点击 check out按钮 5. 之后会提示绑定XYK&#xff0c;这里我是用虚拟XYK开卡平台进行支付的. 6. 确认订单无误后点击Place you…...

SEACALL海外呼叫中心系统的优势包括

SEACALL海外呼叫中心系统的优势包括 封卡封号问题解决 海外呼叫中心系统通过API开放平台能力&#xff0c;定制电话营销系统&#xff0c;提供多项功能如自动拨打、智能应答、真人语音交互等&#xff0c;帮助企业克服员工离职率高、客户资源流失严重等挑战。 - 高级管理者操控 …...

Painter:使用视觉提示来引导网络推理

文章目录 1. 论文2. 示意图3. 主要贡献4. 代码简化 1. 论文 paper:Images Speak in Images: A Generalist Painter for In-Context Visual Learning github:https://github.com/baaivision/Painter 2. 示意图 3. 主要贡献 在 In-context Learning 中&#xff0c;作为自然语言…...

Fedora Linux 38 安装数学动画制作工具manimgl工具包

manimgl可以制作数学动画&#xff0c;它使用的是Python编程语言。 这里介绍他在Fedora Linux 38下的安装过程。 1. sudo dnf update 2. sudo dnf install python3-devel python3-pip python3-tools -y 3. sudo dnf install python3-numpy python3-scipy python3-sympy -y …...

行业追踪,2023-10-26

自动复盘 2023-10-26 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…...

Android 和 iOS APP 测试的那些区别

目前市面上主流的移动操作系统就是 Android 和 iOS 两种&#xff0c;移动端测试本身就跟 Web 应用测试有自己的专项测试&#xff0c;比如安装、卸载、升级、消息推送、网络类型测试、弱网测试、中断测试、兼容性测试等都是区别于 Web 应用需要关注的测试领域。 那么&#xff0…...

利用nicegui开发ai工具示例

from fastapi import FastAPI import uvicorn from nicegui import uiclass PipRequirement:def __init__(self):ui.label("依赖安装与依赖展示")class BasicSettings:def __init__(self):self.project_select ui.select(["test"], label"项目选择&q…...

HarmonyOS鸿蒙原生应用开发设计- 流转图标

HarmonyOS设计文档中&#xff0c;为大家提供了独特的流转图标&#xff0c;开发者可以根据需要直接引用。 开发者直接使用官方提供的流转图标内容&#xff0c;既可以符合HarmonyOS原生应用的开发上架运营规范&#xff0c;又可以防止使用别人的图标侵权意外情况等&#xff0c;减…...

postgresql14管理(六)-备份恢复

定义 备份&#xff08;backup&#xff09;&#xff1a;通过物理复制或逻辑导出的方式&#xff0c;将数据库的文件或结构和数据拷贝到其他位置进行存储&#xff1b; 还原&#xff08;restore&#xff09;&#xff1a;是一种不完全的恢复。使用备份文件将数据库恢复到备份时的状…...

配置Sentinel 控制台

1.遇到的问题 服务网关 | RuoYi 最近调试若依的微服务版本需要用到Sentinel这个组件&#xff0c;若依内部继承了这个组件连上即用。 Sentinel是阿里巴巴开源的限流器熔断器&#xff0c;并且带有可视化操作界面。 在日常开发中&#xff0c;限流功能时常被使用&#xff0c;用…...

【漏洞复现】酒店宽带运营系统RCE

漏洞描述 安美数字 酒店宽带运营系统 server_ping.php 远程命令执行漏洞 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c;遵守公共秩序&#xff0c;尊重社会公德&#xff0c;不得利用网络从事危害国家安全、荣誉和利益&#xff…...

Autojs 利用OpenCV识别棋子之天天象棋你马没了

本例子通过代码像你介绍利用OpenCV实现霍尔找圆的方法定位棋子位置 通过autojs脚本实现自动点击棋子 开源地址 https://github.com/Liberations/TtxqYourHorseIsGone/blob/master/main.js AutoXJs https://github.com/kkevsekk1/AutoX/releasesauto() //安卓版本高于Android 9…...

好数组——尺取法

好数组 给定一个长度为 n 的数组 a&#xff0c;计算数组 a 中所有子数组中好数组的数目。 好数组定义如下&#xff1a; 对于数组 al ,al1, ⋯ ,ar &#xff0c;若数组中所有数的质因数种类数不超过 k&#xff0c;则称为好数组。 Input 输入的第一行包含两个正整数 n,k (1≤…...

【Linux】Ubuntu升级nodejs版本

在下载nvm对nodejs版本进行管理时&#xff0c;由于网络因素一直下载失败&#xff0c;于是采用了新的方法对nodejs版本进行升级。 首先我们先查询一下现存的nodejs版本号&#xff0c;发现是12 我们下载一个名为n的软件包&#xff0c;n 是一个非常方便的 Node.js 版本管理工具&am…...

二维码智慧门牌管理系统升级解决方案:一级属性 二级属性

文章目录 前言一、什么是智慧门牌管理系统&#xff1f;二、一级属性 vs. 二级属性三、升级中的实践意义 前言 在本文中&#xff0c;我们将深入探讨二维码智慧门牌管理系统的升级解决方案&#xff0c;特别聚焦于一级属性和二级属性的关键概念。我们将详细解释这些概念&#xff…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

高分辨率图像合成归一化流扩展

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 摘要 我们提出了STARFlow&#xff0c;一种基于归一化流的可扩展生成模型&#xff0c;它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流&#xff08;TARFlow&am…...

AWS vs 阿里云:功能、服务与性能对比指南

在云计算领域&#xff0c;Amazon Web Services (AWS) 和阿里云 (Alibaba Cloud) 是全球领先的提供商&#xff0c;各自在功能范围、服务生态系统、性能表现和适用场景上具有独特优势。基于提供的引用[1]-[5]&#xff0c;我将从功能、服务和性能三个方面进行结构化对比分析&#…...