【学习笔记】锁+死锁+gdb调试死锁

一、互斥锁(std::mutex)

最基本的锁类型,提供排他性访问,同一时间仅允许一个线程持有锁。

#include <iostream>
#include <mutex>
#include <thread>std::mutex mtx;  // 全局互斥锁
int shared_data = 0;  // 共享资源void increment() {for (int i = 0; i < 100000; ++i) {std::lock_guard<std::mutex> lock(mtx);  // 自动加锁++shared_data;  // 临界区}  // 作用域结束,自动解锁
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final value: " << shared_data << std::endl;  // 输出 200000return 0;
}

二、读写锁(std::shared_mutex)

多读单写锁,允许多个线程同时读,但写时独占。适用于读多写少的场景。

#include <shared_mutex>  // C++17 及以上
#include <thread>
#include <vector>
#include <iostream>std::shared_mutex rw_mutex;
int shared_data = 0;// 读操作(允许多线程并发)
void reader(int id) {for (int i = 0; i < 1000; ++i) {std::shared_lock<std::shared_mutex> lock(rw_mutex);  // 共享锁(读锁)std::cout << "Reader " << id << ": " << shared_data << std::endl;}
}// 写操作(独占)
void writer() {for (int i = 0; i < 10; ++i) {std::unique_lock<std::shared_mutex> lock(rw_mutex);  // 独占锁(写锁)++shared_data;std::cout << "Writer updated: " << shared_data << std::endl;}
}int main() {std::vector<std::thread> readers;for (int i = 0; i < 5; ++i) {readers.emplace_back(reader, i);}std::thread w(writer);for (auto& t : readers) t.join();w.join();return 0;
}

std::shared_lock:用于读操作,允许多个线程同时持有。

std::unique_lock:用于写操作,独占资源,同一时间仅允许一个线程持有。

三、高级锁管理(std::unique_lock)

std::unique_lock 是一种比 std::lock_guard (自动加锁)更灵活的锁管理工具,主要用于需要手动控制锁的生命周期的场景。

比如说想在某一处执行的地方,某一个变量的赋值之前加锁,赋值完毕之后解锁,比较灵活,但是需要注意解锁。

#include <mutex>
#include <thread>std::mutex mtx;void worker() {std::unique_lock<std::mutex> lock(mtx, std::defer_lock);  // 构造时不加锁// 执行无需锁的操作...lock.lock();  // 手动加锁// 临界区lock.unlock();  // 手动解锁// 执行其他无需锁的操作...
}

std::unique_lock 在析构时会自动解锁,因此忘记手动解锁不会导致死锁,但可能导致锁持有时间过长,降低并发性能。

四、死锁

https://www.51cto.com/article/623760.html

1、死锁条件

死锁的四个条件:

​ ● 不可抢占(no preemption):系统资源不能被强制从一个进程(线程)中退出,已经获得的资源在未使用完之前不能被抢占。

​ ● 占有并等待(hold and wait):一个进程(线程)因请求资源阻塞时,对已获得的资源保持不放。

​ ● 互斥(mutual exclusion):资源只能同时分配给一个进程(线程),无法多个进程(线程)共享。

​ ● 循环等待(circular waiting):一系列进程(线程)互相持有其他进程(线程)所需要的资源。

只有同时满足以上四个条件,才会产生死锁,想要消除死锁只需要破坏其中任意一个条件即可。

using std::cout; std::mutex mutex1; 
std::mutex mutex2; 
std::mutex mutex3; void FuncA() { std::lock_guard<std::mutex> guard1(mutex1);  // 获取mutex1std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒std::lock_guard<std::mutex> guard2(mutex2);  // 获取mutex2(如果已被B持有,则阻塞)std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒
} void FuncB() { std::lock_guard<std::mutex> guard2(mutex2);  // 获取mutex2std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒std::lock_guard<std::mutex> guard3(mutex3);  // 获取mutex3(如果已被C持有,则阻塞)std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒
} void FuncC() { std::lock_guard<std::mutex> guard3(mutex3);  // 获取mutex3std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒std::lock_guard<std::mutex> guard1(mutex1);  // 获取mutex1(如果已被A持有,则阻塞)std::this_thread::sleep_for(std::chrono::seconds(1));  // 休眠1秒
} int main() { std::thread A(FuncA); std::thread B(FuncB); std::thread C(FuncC); std::this_thread::sleep_for(std::chrono::seconds(5)); // 尝试回收子线程if (A.joinable()) A.join(); if (B.joinable()) B.join(); if (C.joinable()) C.join(); cout << "hello\n";  // 永远不会执行   return 0; 
} 

2、gdb调试死锁

直接gdb+可执行程序,应该会什么都不打印,一直鼠标跳动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线程 1 (LWP 3097)

  • 角色:主线程(从main函数启动的线程)。
  • 状态:阻塞在futex系统调用,等待某个条件(可能是等待子线程结束)。
  • 关键点expected=3100表明它在等待线程 ID 为 3100 的子线程(即 LWP 3100)。

线程 2 (LWP 3100)

  • 角色:执行FuncA()的线程(根据锁地址匹配)。
  • 状态:阻塞在mutex2(地址0x55555555a1a0)上。
  • 关键点expected=2表示它期望锁的状态为 2(可能是 “已锁定”),但当前锁被其他线程持有。

线程 3 (LWP 3101)

  • 角色:执行FuncB()的线程。
  • 状态:阻塞在mutex3(地址0x55555555a1e0)上。

线程 4 (LWP 3102)

  • 角色:执行FuncC()的线程。

  • 状态:阻塞在mutex1(地址0x55555555a160)上。

  • 等待的锁:线程 2 在等待mutex2,线程 3 在等待mutex3,线程 4 在等待mutex1

  • 已持有的锁:需结合源代码逻辑推断(例如线程 2 已持有mutex1,因为它在等待mutex2之前获取了mutex1)。

死锁原因分析:

结合你的原始代码:

  1. 线程 2(FuncA) 已持有mutex1,正在等待mutex2
  2. 线程 3(FuncB) 已持有mutex2,正在等待mutex3
  3. 线程 4(FuncC) 已持有mutex3,正在等待mutex1

形成循环依赖链:线程 2 → 线程 3 → 线程 4 → 线程 2,导致死锁。

在这里插入图片描述

死锁原因分析:

结合你的原始代码:

  1. 线程 2(FuncA) 已持有mutex1,正在等待mutex2
  2. 线程 3(FuncB) 已持有mutex2,正在等待mutex3
  3. 线程 4(FuncC) 已持有mutex3,正在等待mutex1

形成循环依赖链:线程 2 → 线程 3 → 线程 4 → 线程 2,导致死锁。

(gdb) thread apply all bt 也可以运行以下命令查看所有线程的堆栈

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

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

相关文章

Flutter中将bytes转换成XFile对象上传

在Flutter中将字节数据(bytes)转换为XFile对象并上传可以通过以下步骤实现&#xff1a; 1.字节数据转临时文件 首先需要将字节数据写入临时文件&#xff0c;可以使用dart的File类实现&#xff1a; final tempDir await getTemporaryDirectory(); final file File(${tempDi…

饼图:数据可视化的“切蛋糕”艺术

饼图&#xff0c;作为数据可视化家族中最经典、最易识别的成员之一&#xff0c;其核心功能如同其名——像切分蛋糕一样&#xff0c;直观展示一个整体&#xff08;100%&#xff09;被划分为若干组成部分的比例关系。 往期文章推荐: 20.用Mermaid代码画ER图&#xff1a;AI时代的…

Flutter - 原生交互 - 相机Camera - 曝光,缩放,录制视频

曝光 Flutter上CupertinoSlider组件的样式是iOS上的Slider,使用该组件控制曝光量, Camera插件提供的API是CameraController的 Future<double> setExposureOffset(double offset) async {... }最后调用iOS端的系统方法控制曝光值 - (void)setExposureTargetBias:(floa…

Python中布尔值在函数中的巧妙运用

在 Python 中&#xff0c;布尔值&#xff08;True 和 False&#xff09;不仅可以用于简单的条件判断&#xff0c;还可以在函数中发挥强大的作用。通过合理使用布尔值&#xff0c;你可以使函数更加灵活、高效且易于理解。今天&#xff0c;就让我们一起深入探讨如何在函数中巧妙运…

解决sql查询中in查询项过多时很慢的问题

最近遇到查询一张大数据量表时&#xff0c;需要对一个字段做in查询&#xff0c;in中的元素数量可能达到几千个&#xff0c;即使对这个字段加上索引&#xff0c;速度也慢到无法接受 示例表结构如下&#xff1a; 表中有几十万的数据&#xff0c;且example_id和data_id字段加了联…

Spring---Spring MVC 执行流程

SpringMVC执行流程分为两个&#xff1a;前后端分离与视图阶段&#xff08;不分离&#xff09; 视图阶段&#xff08;JSP/Thymeleaf/Freemarker&#xff09; SpringMVC 前后端分离阶段 SpringMVC中重要组建有哪些&#xff1f; 前端控制器&#xff08;DispatcherServlet&#x…

Llama 4模型卡片及提示词模板

Llama 4模型卡片及提示词模板 Llama 4 模型卡及提示格式介绍 Llama 4 模型概述 Llama 4 是一系列预训练和指令微调的混合专家(Mixture-of-Experts, MoE)大语言模型,包含两种规模:Llama 4 Scout和Llama 4 Maverick。该模型针对多模态理解、多语言任务、编码、工具调用及智…

使用Advanced Installer软件将winform程序打包成exe安装文件

使用Advanced Installer软件将winform程序打包成exe安装文件_c#程序打包软件-CSDN博客 软件的下载连接 https://download.csdn.net/download/qq_20222919/87780646

NDS 中文游戏全集下载 任天堂NDS简介NDS支持GBA游戏

这是一份关于任天堂NDS游戏及其平台的简介&#xff1a; 游戏全集打包下载 https://pan.quark.cn/s/8805da9a09c4 NDS 是什么&#xff1f; 全称&#xff1a; Nintendo DS (NDS)类型&#xff1a; 由任天堂开发和发行的掌上游戏机。世代&#xff1a; 第七世代游戏机 (与PSP、Wii…

Kamailio rtpengine_subscribe_request

master 版本的 rtpengine 新增了函数 rtpengine_subscribe_request 应该是 siprec 增加的 改天做下测试 参考链接&#xff1a; https://lists.kamailio.org/mailman3/hyperkitty/list/sr-userslists.kamailio.org/thread/Q7YJDVBHZX4BIWG23VRVRYW7N5SAAUOR/ https://kamai…

Java八股文——计算机网络「网络模型篇」

什么是OSI七层模型&#xff1f; 面试官您好&#xff0c;OSI&#xff08;Open Systems Interconnection&#xff09;七层模型&#xff0c;是由国际标准化组织&#xff08;ISO&#xff09;提出的一个网络互联的开放式参考模型。 它是一个理论上的、概念性的框架&#xff0c;其核…

国产服务器【银河麒麟v10】【CPU鲲鹏920】部署Nacos

目录 准备工作开始安装1. 下载nacos2. 启动3. 检查 结束 准备工作 环境要求&#xff1a;Linux虚拟机nacos2.3.2 安装包 开始安装 1. 下载nacos 方式1 wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz方式2 去官网自行下载所需版…

一款强大的音视频处理工具--FFmpeg-2--常用音频处理示例

1、查看音频文件详细信息 opus&#xff0c;wav&#xff0c;pcm等音频格式都适用。 ffprobe -i 1.opus说明&#xff1a; Input 0, ogg, from ‘1.opus’: Input 0&#xff1a;表示这是第一个输入文件。ogg&#xff1a;表示该文件封装在Ogg容器格式中&#xff08;Opus通常封装…

在 ArcPy 脚本中进行错误处理和调试

查看错误信息 当捕获到错误后&#xff0c;查看详细的错误信息对于定位问题和解决问题至关重要。 &#xff08;一&#xff09;打印错误消息 在 except 块中&#xff0c;可以直接打印错误对象来获取错误消息。例如&#xff1a; try:arcpy.CalculateField_management("in…

C++11标准(4)——并发库(多线程)

欢迎来到博主的专栏:c杂谈 博主ID&#xff1a;代码小豪 文章目录 thread的相关函数thisthread c11新增了与并发相关的库&#xff0c;包含线程、以及互斥、同步等与线程安全相关的库&#xff0c;与linux中所使用POSIX库不同&#xff0c;并发库是将其进行了封装&#xff0c;不再是…

优化TCP/IP协议栈与网络层

优化TCP/IP协议栈与网络层 在高性能架构中,网络性能往往成为系统吞吐量与响应速度的关键因素之一。而TCP/IP协议栈作为现代互联网通信的核心,其默认配置在高并发场景下常常无法满足大规模分布式系统的性能需求。因此,架构师在构建系统时,有必要对TCP/IP协议栈及其所在的网…

Nginx常见功能

Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;除了基本的 Web 服务功能外&#xff0c;它还支持许多高级功能。以下是 Nginx 常用的一些功能及其设置方法&#xff1a; 1. 反向代理 反向代理是 Nginx 最常用的功能之一&#xff0c;用于将客户端请求转发给后端服务器&a…

UniSAL:用于组织病理学图像分类的统一半监督主动学习方法|文献速递-深度学习医疗AI最新文献

Title 题目 UniSAL: Unified Semi-supervised Active Learning for histopathologicalimage classification UniSAL&#xff1a;用于组织病理学图像分类的统一半监督主动学习方法 01 文献速递介绍 组织病理学图像在癌症筛查、诊断及治疗决策中起着关键作用&#xff0c;有助…

智慧园区建设资料合集(Wordppt原件)

化工园区安全风险智能化管控平台.docx 数字孪生赋能的智慧园区物联网云平台建设方案.pptx 园区智慧安防解决方案.docx 新型智慧园区规划设计方案.pptx 新型智慧园区建设方案.docx 园区大数据治理解决方案.pptx 智慧产业园区综合解决方案.docx 智慧工业园区大数据云平台解决方案…

好玩的镜像汇总

一些镜像仓库汇总 https://github.com/code-lives/Nas-Docker https://github.com/TWO-ICE/Awesome-NAS-Docker image-matting是一款集成了AI大模型的&#xff0c;支持容器化部署的短平快抠图工具 https://mp.weixin.qq.com/s/A1VKAYaDdbCs2o1L4ZYkSw Moodist是一个有助于专注…