C++面试:死锁的危害、出现原因、解决方法

        

目录

死锁的危害

死锁出现的原因

死锁的解决方法


        死锁是计算机科学中一个非常重要的概念,特别是在多线程、并发编程以及数据库管理系统等领域中。下面是关于死锁的危害、出现原因和解决方法的基础概述:

死锁的危害

  1. 资源浪费:死锁导致系统中的资源被无效地占用,而无法释放,从而浪费了系统资源。
  2. 程序停滞:死锁会导致相关进程或线程被永久阻塞,无法继续执行,从而影响系统的正常运行。
  3. 系统崩溃:在一些情况下,死锁可能导致系统崩溃,从而造成严重的后果。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mutex1;
std::mutex mutex2;void function1() {std::lock_guard<std::mutex> lock1(mutex1);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock2(mutex2);std::cout << "Function 1 acquired mutex1 and mutex2\n";
}void function2() {std::lock_guard<std::mutex> lock2(mutex2);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock1(mutex1);std::cout << "Function 2 acquired mutex2 and mutex1\n";
}int main() {std::thread t1(function1);std::thread t2(function2);t1.join();t2.join();return 0;
}

        这段代码创建了两个线程,每个线程都试图获取两个互斥量(mutex1mutex2)的所有权,但是获取的顺序是相反的。如果这两个线程同时运行,就会发生死锁,因为一个线程持有了mutex1,但试图获取mutex2,而另一个线程持有了mutex2,但试图获取mutex1,从而导致彼此互相等待,最终导致程序停滞。

        为了避免死锁,需要确保在多个线程中获取互斥量的顺序是一致的。

 

死锁出现的原因

死锁通常发生在多个进程或线程之间,由于彼此持有对方所需的资源而导致的循环等待。常见的原因包括:

  1. 资源竞争:多个进程争夺有限的资源,但由于资源分配不当或者进程执行顺序不当,导致发生死锁。
  2. 进程推进顺序不当:当多个进程按照不同的顺序获取资源,但释放资源的顺序不当时,可能导致死锁。
  3. 并发访问共享资源:多个进程同时访问共享资源,并且不加控制地相互等待对方释放资源,从而导致死锁。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mutex;void access_shared_resource(int thread_id) {std::lock_guard<std::mutex> lock(mutex); // 获取互斥锁std::cout << "Thread " << thread_id << " is accessing the shared resource.\n";std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟访问共享资源需要的时间// 假设这里需要访问另一个共享资源std::lock_guard<std::mutex> lock2(mutex); // 再次获取互斥锁,尝试访问另一个共享资源std::cout << "Thread " << thread_id << " is accessing another shared resource.\n";
}int main() {std::thread t1(access_shared_resource, 1);std::thread t2(access_shared_resource, 2);t1.join();t2.join();return 0;
}

        在这个例子中,两个线程 t1t2 同时尝试访问共享资源,并且在获取第一个共享资源后,又尝试获取另一个共享资源。然而,它们没有适当地协调共享资源的访问顺序,而是简单地相互等待对方释放资源,这可能导致死锁。

        这个例子展示了并发访问共享资源时可能发生的死锁情况,因为多个进程(或线程)同时访问共享资源,并且不加控制地相互等待对方释放资源,从而导致了死锁的发生。

 

死锁的解决方法

  1. 避免死锁:通过合理地设计算法和资源分配策略,使系统尽量避免进入死锁状态。比如,银行家算法等。
  2. 检测与恢复:设计算法检测系统中的死锁,并且在检测到死锁时采取相应的措施进行恢复,如中断一些进程或者回滚操作。
  3. 预防死锁:采用一些方法预防死锁的发生,例如破坏死锁产生的必要条件之一,比如破坏循环等待条件、破坏互斥条件等。
  4. 资源分配策略:采用合适的资源分配策略,确保资源的有效利用,并且尽量减少死锁的发生。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mutex1;
std::mutex mutex2;void function1() {std::lock(mutex1, mutex2); // 使用 std::lock 来一次性获取多个互斥量的所有权,避免死锁std::lock_guard<std::mutex> lock1(mutex1, std::adopt_lock); // 使用 std::adopt_lock 参数表示已经拥有互斥量的所有权std::lock_guard<std::mutex> lock2(mutex2, std::adopt_lock);std::cout << "Function 1 acquired mutex1 and mutex2\n";// 这里执行任务
}void function2() {std::lock(mutex1, mutex2); // 使用 std::lock 来一次性获取多个互斥量的所有权,避免死锁std::lock_guard<std::mutex> lock1(mutex1, std::adopt_lock); // 使用 std::adopt_lock 参数表示已经拥有互斥量的所有权std::lock_guard<std::mutex> lock2(mutex2, std::adopt_lock);std::cout << "Function 2 acquired mutex1 and mutex2\n";// 这里执行任务
}int main() {std::thread t1(function1);std::thread t2(function2);t1.join();t2.join();return 0;
}

        在这个例子中,function1function2 都试图获取 mutex1mutex2 的所有权。通过使用 std::lock 函数一次性获取多个互斥量的所有权,并且使用 std::adopt_lock 参数表示已经拥有互斥量的所有权,可以避免死锁的发生。这种方式可以保证无论线程以什么顺序获取锁,都不会发生死锁。 

        这些方法通常是根据具体情况和需求来选择和应用的,不能一概而论。在实际应用中,通常需要根据系统的特点和需求综合考虑,选择合适的死锁处理方法。

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

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

相关文章

设计模式:模版模式

模板模式&#xff08;Template Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个操作中的算法骨架&#xff0c;将一些步骤的具体实现延迟到子类中。模板模式使得子类可以在不改变算法结构的情况下重新定义算法的某些步骤。 在模板模式中&#xff0c;将算法的…

C++ 高频考点

1. C/C内存有哪几种类型&#xff1f; C中&#xff0c;内存分为5个区&#xff1a;堆(malloc)、栈(如局部变量、函数参数)、程序代码区&#xff08;存放二进制代码&#xff09;、全局/静态存储区&#xff08;全局变量、static变量&#xff09;和常量存储区&#xff08;常量&…

Python Sanic 异步 Web 框架

Sanic 是一个基于 Python 3.6 的异步 Web 框架&#xff0c;它使用了 Python 的 async/await 语法来实现高效的非阻塞 IO 操作。 Sanic 的主要作用是提供一个快速、轻量级的方式来构建异步 Web 服务&#xff0c;适用于处理大量并发请求的场景。 以下是一个简单的示例代码&…

YOLOv9来了!实时目标检测新SOTA

先上一把网上的测试效果对比: YOLOv9架构图 速度论文 代码&#xff1a;GitHub - WongKinYiu/yolov9: Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information 论文&#xff1a;[2402.13616] YOLOv9: Learning What You…

每日coding 7. 整数反转 69. x 的平方根

7. 整数反转 给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&am…

HTTP/HTTPS协议

什么是HTTP协议 HTTP被称为超文本传输协议(里面不仅仅可以是字符串,还可以是图片,特殊字符等),这是一种应用非常广泛的应用层协议. HTTP协议诞生于1991年,现在是最主流使用的一种应用层协议.它从诞生到现在为止迭代了多个版本. 但目前最主流使用的还是HTTP1.1和HTTP2.0. HTTP协…

Java数据结构---初识集合框架

目录 一、什么是集合框架 二、集合框架的重要性 三、背后涉及的数据结构及算法 1.什么是数据结构 2.容器背后对应的数据结构 3.相关的Java知识 4.什么是算法 一、什么是集合框架 Java 集合框架 Java Collection Framework &#xff0c;又被称为容器 container &#xff0…

Unity编辑器内工程文件重命名|Project视图文件名修改

Unity编辑器内文件重命名 前言大项内容一使用方法代码展示 总结 前言 本文代码可以一键更改Project视图的文件名字 在当前文件名的状态下增加一段字符区分文件。 大项内容一 功能是因为在给其他人导入项目资源时有重复的资源的时候&#xff0c;资源会产生覆盖的问题。所以直…

RabbitMQ——消息应答和持久化

文章目录 RabbitMQ——消息应答和持久化1、消息应答1.1、概念1.2、手动应答示例 2、持久化 RabbitMQ——消息应答和持久化 1、消息应答 1.1、概念 概念 消息应答机制是指消费者在消费消息后向 RabbitMQ 确认&#xff08;acknowledge&#xff09;已经成功处理了消息。 这个机…

家用办公主机需要多少钱?推荐主机选购攻略!!

1.头部部分 本文将长期保持更新&#xff0c;您可以保存并随时查看。 过去推荐的 主持人推荐 以下家庭办公主机均采用性能强劲的12/13代i5配置&#xff0c;可以完美应对日常办公、平面设计、编辑等使用场景。 主机价格在4K左右&#xff0c;自带显示器&#xff0c;并附有三到…

xss靶场实战(xss-labs-master靶场)

xss-labs-master靶场链接&#xff1a;https://pan.baidu.com/s/1X_uZLF3CWw2Cmt3UnZ1bTw?pwdgk9c 提取码&#xff1a;gk9c xss-labs level 1 修改 url 地址中的name<script>alert(1)</script>&#xff0c;便可以通关 level 2 在搜索框中输入的 JS 代码无法执行 …

leetcode704--数组元素查找--二分法查找算法

第一部分---数组的基础知识介绍&#xff1a; 1.数组的定义&#xff1a;数组是存放在连续内存空间上的相同数据类型的数据的集合&#xff1b; 2.数组可以通过下标索引的方式获取到下标对应的数据&#xff1b; 3.数组下标是从0开始的&#xff0c;数组的内存空间地址是连续的&a…

用户体验设计师如何在 2024抢占先机?

01. 严峻的经济形势和就业市场 我们生活在一个通货膨胀的时代。就从超市抓几个苹果、卷心菜、鸡蛋&#xff0c;看看价格吧&#xff01;我不得不多次检查收据&#xff0c;因为我简直不敢相信。外出就餐费用上涨了 10-20%&#xff0c;现在 Spotify 和 YouTube 要求收取更高的订阅…

【达梦数据库】undo_retention 测试

最近遇见如下问题 【问题背景】备库抽数报错回滚记录版本太旧&#xff0c;涉及表为日志表&#xff08;含有两个text列&#xff09;&#xff0c;主库undo_retention90 备库undo_retention3600&#xff0c;主库每分钟有这个表的写入&#xff08;insert update&#xff09;&#x…

【力扣hot100】刷题笔记Day13

前言 元宵节快乐 ~ 周六在图书馆快乐刷题&#xff01;继续二叉树&#x1f374; 543. 二叉树的直径 - 力扣&#xff08;LeetCode&#xff09; 递归后序 class Solution:def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:self.res 0 # 记录最长路径# 递归…

使用python写一个修改execl表格的脚本

使用的前提记得安装python的环境。 import os import pandas as pddef listdir(path): #传入根目录file_list []for file in os.listdir(path):file_path os.path.join(path, file) #获取绝对路径if os.path.isdir(file_path): #如果还是文件夹&#xff0c;就继续迭代本函数…

GPT-4:开启人工智能新纪元的多功能引擎

随着人工智能技术的飞速发展&#xff0c;GPT-4&#xff08;Generative Pre-trained Transformer 4&#xff09;作为最新一代的语言模型&#xff0c;已经成为了推动科技创新、优化人机交互体验的关键力量。本文将深入探讨GPT-4的核心作用&#xff0c;以及它如何在各个领域中展现…

STM32通用定时器输入捕获

通用定时器输入捕获部分框图介绍 通用定时器输入捕获脉宽测量原理 要测量脉宽的高电平的时间&#xff1a;t2-t1&#xff08;脉宽下降沿时间点-脉宽上升沿时间点&#xff09; 假设&#xff1a;递增计数模式 ARR&#xff1a;自动重装载寄存器的值 CCRx1&#xff1a;t1时间点CCRx…

2024最新可用免费天气预报API接口

天气API接口数据, 数据字段最全&#xff0c;免费&#xff0c;稳定的实况天气预报接口 5分钟左右更新一次&#xff0c;支持全国3000多个市区县, 包含基本天气信息、24小时逐小时天气、气象预警列表、湿度、能见度、气压、降雨量、紫外线、风力风向风速、日出日落、空气质量、pm2…

细粒度目标检测问题剖析

问题剖析 相对于一般目标检测任务&#xff0c;细粒度目标更容易出现类内差异大、类间差异小等现象。 所谓细粒度目标识别&#xff0c;是指在目标检测的基础上&#xff0c;识别出目标的具体型号与类别&#xff0c;例如不只识别出飞机目标&#xff0c;还能识别出飞机型号。粗粒…