常见的死锁情况分析

server/2025/3/16 21:31:57/

 死锁

定义:

是指多个进程或线程在执行过程中,由于竞争资源或因通信的需要而产生的相互等待的状态,使得它们无法继续执行下去(单线程中使用不恰当也会导致死锁问题)。

如下为常见的死锁原因:

a. 互斥条件

至少有一个资源必须处于不可共享的状态,即某个资源在同一时刻只能被一个线程或进程占用。如果其他线程或进程请求该资源,它们必须等待该资源被释放。

b. 请求与保持条件

一个线程已经持有至少一个资源,但又请求其他线程占有的资源,并且在等待的过程中保持对已占有资源的控制。

c. 不剥夺条件

已经分配给一个线程的资源,在该线程使用完之前不能被强制剥夺。资源只能由线程自己释放。

d. 循环等待条件

在一个线程的等待链中,存在一个环路,使得每个线程都在等待另一个线程释放资源。即形成了一种“循环等待”状态。

如下为常见的死锁原因对应代码分析:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;std::mutex mtxAB;
std::recursive_mutex rmtxAB;
std::mutex mtx_C;
std::mutex mtx_D;void B(void);
void B1(void);// 死锁1——demo1
void A(void)
{lock_guard<std::mutex> lock(mtxAB);// 保护资源B();
}void B(void)
{A();
}// 死锁2——demo2
void A1(void)
{// lock_guard<std::mutex> lock(mtxAB);// 解决这种死锁方法lock_guard<std::recursive_mutex> lock(rmtxAB);// 保护资源B1();
}void B1(void)
{// lock_guard<std::mutex> lock(mtxAB);// 解决这种死锁方法lock_guard<std::recursive_mutex> lock(rmtxAB);    // 保护资源
}// 死锁3——demo1
void C(void)
{// 先获取mtx_Cstd::lock_guard<std::mutex> lock1(mtx_C);// 保护资源printf("C: operate something\n");// 再获取mtx_Dstd::lock_guard<std::mutex> lock2(mtx_D);
}void D(void)
{// 先获取mtx_Dstd::lock_guard<std::mutex> lock1(mtx_D);// 保护资源printf("D: operate something\n");// 再获取mtx_Cstd::lock_guard<std::mutex> lock2(mtx_C);
}int main()
{// test死锁1——demo1// A();// test死锁2——demo2A1();    // test死锁3——demo3// std::thread thread[] = {//     std::thread(C),//     std::thread(D)// };// for(auto& t : thread){//     t.join();// }// 死锁4...printf("the main normally exit!\n");return 0;
}

那么如何解决死锁呢? 

1. 避免嵌套锁(或锁的顺序)

最常见的避免死锁的方法之一是确保线程按固定的顺序获取锁。比如,规定所有线程首先获得 MutexA 锁,然后再获得 MutexB 锁,而不允许线程先获得 MutexB 锁再去获得 MutexA 锁。

(可自行尝试解决如上代码中demo3)

2. 使用超时机制

设置锁的超时时间。如果线程在获取锁时超时了,就主动释放已持有的锁,并重新尝试或返回失败,这样就可以避免死锁的发生。

3. 死锁检测与恢复

某些系统会周期性检查是否存在死锁。如果发现死锁状态,可以通过终止一个或多个线程、回滚某些操作或强制释放锁来恢复。

4. 使用递归锁

在一些情况下,如果锁定的资源是递归锁,同一线程可以多次获取锁,而不会导致死锁。这对于某些设计中需要递归调用的情况有效。

end!

各位大佬有什么补充,或者需要更正的欢迎指出哈~


http://www.ppmy.cn/server/175527.html

相关文章

股指期货的锁仓是什么意思?

股指期货锁仓是指投资者在持有某一方向仓位的同时&#xff0c;反向开立一个数量相等但方向相反的仓位。这种操作类似于给持仓“上锁”&#xff0c;无论市场价格如何波动&#xff0c;锁仓后的盈亏状态都不会再发生变化。锁仓的主要目的是在不确定的市场环境下&#xff0c;锁定当…

利用Python爬虫根据关键词获取商品列表

在电商领域&#xff0c;通过关键词搜索商品并获取商品列表是常见的需求。本文将详细介绍如何使用Python编写爬虫程序&#xff0c;根据关键词获取商品列表&#xff0c;并确保爬虫行为符合平台规范。为了具体展示&#xff0c;我们将以一个假设的电商平台为例&#xff0c;展示如何…

Python 实现的采集诸葛灵签

Python 实现的采集诸葛灵签 项目介绍 这是一个基于 Python 开发的诸葛灵签数据采集和展示项目。通过爬虫技术获取诸葛神签的签文和解签内容&#xff0c;并提供数据存储和查询功能。 项目结构 zhuge/├── zhuge_scraper.py # 爬虫主程序├── zhuge_pages/ # 数据存储目录…

TCP 三次握手四次挥手过程详解

注&#xff1a;本文为 “TCP 的三次握手与四次挥手” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;未整理去重。 英文引文第二篇&#xff0c;实为国内《稀土掘金技术社区》文章&#xff0c;没检索到原文&#xff0c;此处 “出口转内销” 。 如有内…

MCU的工作原理:嵌入式系统的控制核心

MCU的工作原理可以概括为以下几个步骤&#xff1a; 1. 初始化 上电后&#xff0c;MCU从Flash存储器中加载程序代码&#xff0c;并初始化外设和寄存器。 2. 任务执行 根据程序逻辑&#xff0c;MCU执行数据处理、外设控制和通信等任务。通过中断系统实时响应外部事件。 3. 低…

Android电量与流量优化

Android电量与流量优化 一、电量优化基础 1.1 电量消耗原理 Android设备的电量消耗主要来源于以下几个方面: 屏幕显示:屏幕是耗电量最大的硬件之一,尤其是高亮度和高刷新率的屏幕。CPU处理:CPU执行计算任务时会消耗大量电量,尤其是高负载运算。网络通信:移动数据、Wi-…

贪心算法简介(greed)

前言&#xff1a; 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每个决策阶段都选择当前最优解的算法策略&#xff0c;通过局部最优的累积来寻求全局最优解。其本质是"短视"策略&#xff0c;不回溯已做选择。 什么是贪心、如何来理解贪心(个人对贪心的…

【机器人-基础知识】标定 - 相机内参求解原理(单应性矩阵、内参约束方程)

1. 求解目标&#xff1a;内参 从世界坐标系到像素坐标系的齐次坐标形式&#xff1a; s [ u v 1 ] K [ R t ] [ X w Y w Z w 1 ] s \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} K \, [\, R \quad t \,] \begin{bmatrix} X_w \\ Y_w \\ Z_w \\ 1 \end{bmatrix} s ​uv1​ ​K…