【线程池项目(四)】项目的死锁问题分析和资源回收机制的改善

在上一篇 【线程池项目(三)】线程池CACHED模式的实现中我们大概说了说cached模式的基本实现,对于多线程编程,我们需要考虑的问题也较于单线程更多、更复杂,经常存在线程同步、资源竞争等复杂的并发控制问题,因此上篇的文末留下了三个问题🤔🤔🤔
在这里插入图片描述
这是本篇博客关注的第一个死锁问题,另一个就是在跨平台编译(Ubuntu20.04)时,由于平台差异化而引起的出现的死锁性问题,下面我们来详细的剖析一下

如果需要与本篇博客完全匹配的实现代码,也可以在 我的gitee 上下载对应的源码

项目经历——基于C++新特性以及模板编程实现的线程池

    • 一、三种状态的可能性死锁问题🧐🧐🧐
    • 二、对应的解决方案😮😮😮
    • 三、资源回收机制的改良😦😦😦
    • 四、平台差异化的死锁性问题(没有发生,代码竟然能跑🤣🤣)
    • 五、对应的解决方案🥹🥹🥹
    • 六、总结😩😩😩

一、三种状态的可能性死锁问题🧐🧐🧐

我们先来看看前两种情况

  1. 🤔 当线程数多余任务队列中的任务数或者是任务队列为空时,在一定的时间内,肯定会有某个或者某些线程处于空闲的wait状态等待任务的到来,如果这时用户准备结束主程序(即执行线程池的析构函数),将isPoolRunning置为false,并进行notEmpty.notify_all()通知,等待在wait上的线程被唤醒往下执行,在下面的if判断语句中满足结束条件,正常的回收线程;cached模式通过自己的回收机制也能正常的回收线程,不会造成死锁问题的发生

  2. 🤔 当某个线程正在执行任务exec且还未执行完时,用户准备结束主程序(即执行线程池的析构函数),析构函数中的语句对正在执行任务的线程没有任何影响,当线程执行任务完成且更新完任务执行完的时间后,同样也能够通过while()的判断条件正常的退出,进而被回收,也不会发生死锁问题

这是第三种情况

  1. 🤔 当某个线程执行任务完成,且用户准备结束主程序(即调用线程池的析构函数)时,线程在isPoolRunning被主程序置为false之前,执行完任务的线程已经进入了外边的while循环,并且还没有执行到fixed模式下的wait,这时主线程往下执行析构函数,通知等待的线程,并等待所有线程被回收,之后执行完任务的线程再往下执行至notEmpyt.wait(),显然现在线程池中只有一个线程等待被唤醒,而用户所在的主线程也阻塞在exitCond_wait()上,出现了死锁现象

在这里插入图片描述

🫠以下是正常结束的执行结果(具有偶然性)

在这里插入图片描述

🫠这是发生死锁问题的执行结果,有一个任务线程没有被回收,主程序线程也被无限期等待

在这里插入图片描述

二、对应的解决方案😮😮😮

来看看修改后的代码
在这里插入图片描述

  • 当主线程执行析构函数时先抢到锁,线程池中的线程会在定义unique_lock上阻塞,进而主线程继续执行通知正在wait的线程,而无论是正在执行任务的线程,还是wait状态的线程,都不会出现死锁问题,因为执行任务的线程不影响,而wait状态的线程会在被唤醒后,也会在if条件下break,正常的被回收
  • 当线程池里面的线程先抢到锁时,主线程线程会阻塞在unique_lock上,线程池里的线程往下执行,无论是执行到wait语句,还是直接获取到任务exec,主程序线程总是会比线程池里的线程慢一步,后执行notify_all()操作来唤醒等待的线程,因此也不会发生死锁问题

三、资源回收机制的改良😦😦😦

前面我们对于线程池的析构函数进行了优化,完善了线程池的资源回收机制,但还是有问题没考虑到,我们资源回收关注的点仅仅是线程,并没有过多的看到任务的具体执行情况,即当线程池要析构、结束时,如果还有用户提交的任务没有执行完,该怎么办 ? 当然,我们很容易想到,既然线程池都已经结束了,那里边正在执行的任务也势必会直接结束。但这仅仅是对我们自己而言,要实现一个完整、通用的系统,我们肯定是需要等待任务执行完毕才行,我们更改以下测试程序,看看会发生什么
在这里插入图片描述
下面是执行结果
在这里插入图片描述
看看,用户如果不需要获取任务执行完毕的返回值(即调用get()方法阻塞),只是让线程池执行任务,他辛辛苦苦提交的任务根本就没有被执行,然而主线程就直接退出了!!!因此我们仍然需要修改我们之前优化过的代码!!!

在这里插入图片描述
图例不太清除,这里就不介绍了,可以在 我的gitee 上下载对应的源码进行对比分析


ubuntu20.04编译动态库g++ threadpool.cpp -fPIC -shared libpool.so -std=c++17
动态库搜索路径/usr/local/lib
头文件搜索路径usr/local/include
测试代码执行命令g++ main.cpp -o a -lpool -lpthread -std=c++17


四、平台差异化的死锁性问题(没有发生,代码竟然能跑🤣🤣)

Visual Stdio 2022 的 condition_variable 底层源码,完善了条件变量的析构函数,正常释放

在这里插入图片描述
Linux系统上 condition_variable 的底层源码,析构函数没有做任何操作
在这里插入图片描述

实际上,我在Linux上运行该项目时,并没有遇到老师提到的这些情况😵😵,这可能是因为我的配置存在问题,或者是因为在后续版本中开发者大佬们解决了这些问题。

五、对应的解决方案🥹🥹🥹

使用Linux环境下的gdb调试,通过gdb attach PID,调试当前正在运行的程序,ps -u可以查看当前正在执行的进程任务,info threads查看所有线程的状态以及当前正在哪个关注线程,thread n关注第n个线程,bt打印该线程执行函数的堆栈信息,进行问题分析。

六、总结😩😩😩

以上内容涉及了《线程池项目(四)》项目中死锁问题的分析以及资源回收机制的改进。关于项目后续采用packaged_task和future进行的二次开发和重构的详情就不介绍了,其源码可在 我的gitee 上找到。这也是本系列《手写线程池》的最后一篇🔚 。未来,我将与大家分享更多项目。我知识有限,博客中还有很多地方需要改进,出现问题希望大佬们能够及时指正,感谢大家的支持!🌻🌻🌻

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习python的第7天,她不再开放她的听歌榜单

我下午登录上小号,打开聊天消息看到了她的回复,我很开心兴奋,可是她不再开放她的听歌榜单了,我感觉得到,我要失恋了。 “因为当年电视上看没有王菲版本的” “行”。 “那你以后还会开放听歌榜单吗?”我…

Linux之部署前后端分离项目

Nginx配置安装 1.安装依赖 我们这里安装的依赖是有4个的 [rootlocalhost opt]# yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.上传解压安装包 [rootlocalhost opt]# tar -xvf nginx-1.13.7.tar.gz -C /usr/local/java/3.安装Nginx &#xff0…

电机控制----电机反电动势波形的测量

电机控制----电机反电动势波形的测量 很多人在开发霍尔传感器方波控制时,在如何准确确定出三相绕组的通电顺序方面存在疑惑,在网上找了很多资料都是只给出了相序表,但是真正拿过来引用时却往往对应不了自己的电机,导致项目开发过…

SpringBoot:数据访问-整合 Druid 配置数据源监控

点击查看数据访问demo&#xff1a;LearnSpringBoot06DataJdbc 点击查看更多的SpringBoot教程 简介 Druid Spring Boot Starter 用于帮助你在Spring Boot项目中轻松集成Druid数据库连接池和监控。 一、添加druid-spring-boot-starter依赖 点击查询最新版 <dependency&g…

[electron]官方示例解析

官方例子 github链接 main.js const { app, BrowserWindow } require(electron)说句实话这里的语法是有部分看不懂的。导入模块虽然electron有很多模块。但是这里只是用到了app 和 BrowserWindow function createWindow () {// Create the browser window.const mainWindo…

流计算之Flink

文章目录 概要有界无界流集群JobManagerTaskManagersTasks 和算子链Task Slots 和资源 小结 概要 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模…

常用芯片学习——YC688语音芯片

YC688 广州语创公司语音芯片 使用说明 YC688是一款工业级的MP3语音芯片 &#xff0c;完美的集成了MP3、WAV的硬解码。支持SPI-Flash、TF卡、U盘三种存储设备。可通过电脑直接更新SPI-Flash的内容&#xff0c;无需上位机软件。通过简单的串口指令即可完成三种存储设备的音频插…

深度学习基础(四)医疗影像分析实战

之前的章节我们初步介绍了卷积神经网络&#xff08;CNN&#xff09;和循环神经网络&#xff08;RNN&#xff09;&#xff1a; 深度学习基础&#xff08;三&#xff09;循环神经网络&#xff08;RNN&#xff09;-CSDN博客文章浏览阅读1.2k次&#xff0c;点赞17次&#xff0c;收…

Java基于SpringBoot的口腔医院管理平台,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

给大家分享一款小程序:AI一秒修图

AI一秒修图 照片修复的AI助手特点&#xff1a;Demo&#xff08;1.选择图片 2.涂抹遮罩 3.消除&#xff09;Product Roadmap (版本演进)Contact-联系我们Reference 照片修复的AI助手 照片修复小小助手是一款快速P图微信小程序&#xff0c;用来消除图片中指定的人和物&#xff…

wpf 简单实验 数据更新 列表更新

1.概要 1.1 需求 一个列表提供添加修改删除的功能&#xff0c;添加和修改的内容都来自一个输入框 1.2 要点 DisplayMemberPath"Zhi"列表.ItemsSource datalist;(列表.SelectedItem ! null)(列表.SelectedItem as A).Zhi 内容.Text;datalist.Remove((列表.Selec…

matlab simulink变压器温度仿真

1、内容简介 略 48-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 matlab simulink变压器温度仿真_哔哩哔哩_bilibili 4、参考论文 略 大型油浸风冷变压器绕组温度场分析_高原 基于顶层油温的变压器绕组热点温度计算改进模型_陈伟根 基于热电类比理论的油浸式电…

【计算机网络】深度学习使用应用层的HTTP协议

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【计算机网络】深度学习使用应用层的HTTP协议 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录 一:HTTP是什么二:HTTP请求1.HTTP请求的组成2.HTTP请求的方法…

面试经典150题【21-30】

文章目录 面试经典150题【21-30】6.Z字形变换28.找出字符串中第一个匹配项的下标68.文本左右对齐392.判断子序列167.两数之和11.盛最多水的容器15.三数之和209.长度最小的子数组3.无重复字符的最长子串30.串联所有单词的子串 面试经典150题【21-30】 6.Z字形变换 对于“LEETC…

Redis实现滑动窗口限流

常见限流算法 固定窗口算法 在固定的时间窗口下进行计数&#xff0c;达到阈值就拒绝请求。固定窗口如果在窗口开始就打满阈值&#xff0c;窗口后半部分进入的请求都会拒绝。 滑动窗口算法 在固定窗口的基础上&#xff0c;窗口会随着时间向前推移&#xff0c;可以在时间内平滑控…

矩阵的导数运算(理解分子布局、分母布局)

矩阵的导数运算(理解分子布局、分母布局) 1、分子布局和分母布局 请思考这样一个问题&#xff0c;一个维度为m的向量y对一个标量x的求导&#xff0c;那么结果也是一个m维的向量&#xff0c;那么这个结果向量是行向量&#xff0c;还是列向量呢&#xff1f; 答案是&#xff1a…

【前端素材】推荐优质医院后台管理系统I-Health平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理和监控网站、应用程序或系统的在线工具。它通常是通过网页界面进行访问和操作&#xff0c;用于管理网站内容、用户权限、数据分析等。后台管理系统是网站或应用程序的控制中心&#xff0c;管理员可以通过后台系统进行各种管理和配置操…

如何用Pytest做性能测试?5个步骤轻松学会!

Pytest其实也是可以做性能测试或者基准测试的。是非常方便的。 可以考虑使用Pytest-benchmark类库进行。 安装pytest-benchmark 首先&#xff0c;确保已经安装了pytest和pytest-benchmark插件。可以使用以下命令安装插件&#xff1a; pip install pytest pytest-benchmark …

无需软件_暂停 Windows更新

按下 WIN 加 R 输入 regedit 进入注册表 点击 HKEY LOCAL-MACHINE 点击 SOFTWARE 点击 Microsoft 点击 WindowsUpdate 点击 UX 点击 Settings 然后空白区点击右键 选择新建&#xff0c;选择项&#xff0c;选择 dword 值 命名为 FlightSettingsMaxPauseDays 基数选择十…

创作纪念日:记录我的成长与收获

机缘 一开始是在我深入学习前端知识的Vue.js框架遇到了一个问题&#xff0c;怎么都解决不了&#xff0c;心烦意乱地来csdn上找解决方法。开心的是真被我找到了&#xff0c;真的很感恩&#xff0c;也意识到在这个平台上分享自己的经验是多么有意义的事情&#xff0c;可能随便的…