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

在上一篇 【线程池项目(三)】线程池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://xiahunao.cn/news/2808654.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

响应式资源素材源码图库下载平台整站系统,附带系统搭建教程

响应式资源素材源码图库下载平台整站系统,可用于做娱乐网 资源网,功能非常的齐全无任何加密也无任何后门!支持支付宝接口。 页面很美观,堪比大型网站的美工,而且页面做的也很人性 化, 用户主要分为两类&am…

【MATLAB源码-第143期】基于matlab的蝴蝶优化算法(BOA)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境: MATLAB 2022a 1、算法描述 蝴蝶优化算法(Butterfly Optimization Algorithm, BOA)是基于蝴蝶觅食行为的一种新颖的群体智能算法。它通过模拟蝴蝶个体在寻找食物过程中的嗅觉导向行为以及随机飞行行为,来探索解空间&a…

Python习题详解

练习&#xff1a; 1&#xff0c;计算100以内奇数的和 #计算100以内所有奇数的和 sum 0 # n 1 # while n < 100: # # sum sum n # sum n # # n n 2 # n 2 # print(sum) n 99 #求偶数时n 100 while n > 0:sum n# n n - 2n - 2 print(sum)2&#xff0c;打印直…

MySQL锁三部曲:临键、间隙与记录的奇妙旅程

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 MySQL锁三部曲&#xff1a;临键、间隙与记录的奇妙旅程 前言临键锁的奥秘间隙锁记录锁 前言 在数据库世界中&#xff0c;锁是维护数据完整性的一种关键机制。而MySQL中的临键锁、间隙锁和记录锁则是锁…

Python零基础安装教程(包含各种安装方案)以及PyCharm安装步骤

文章目录 安装方案介绍安装Python解释器安装Pycharm安装Anaconda方案参考 安装方案介绍 方案1&#xff1a;只安装Python解释器&#xff08;适合小型开发&#xff09; 方案2&#xff1a;安装集成开发环境Anaconda&#xff08;集成了Spyder&#xff0c;JupyterNotebook等编辑器&…

cmd命令开启windows桌面远程控制并设置防火墙允许远程

cmd命令开启桌面远程控制 1、开启之前&#xff1a; 2、使用管理员身份运行cmd 3、执行cmd命令 reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Control\Terminal server" /v fDenyTSConnections /t REG_DWORD /d 0 /f4、如果这台电脑的防火墙打开&#xff…

【buuctf-我吃三明治】

看到这个题&#xff0c;我忽然感觉答案就在中间&#xff0c;三明治笑死了。这张原始 flag 图片包含两张图&#xff0c;为什么是两张图见下&#xff1a; 以FF D9结尾是第一张图片结束&#xff0c;FF D8 FF是第二张图片开始。 两张图片拆出来分别是下面两张&#xff08;当然没什…

Spring Boo项目中方法参数对象中字段上存在的自定义注解如何进行拦截解析

一、前言 在Spring Boot项目开发过程中&#xff0c;我们经常会使用到自定义注解的方式进行业务逻辑开发&#xff0c;此时注解我们一般是放在方法或者类上面&#xff0c;通过AOP切面拦截的方式进行自定义业务逻辑填充。但是如果自定义注解放在类的字段上&#xff0c;此时应该如…

平头哥IP核C906的JTAG调试器DIY教程(一)

背景 最近买了一块基于平头哥C906核&#xff0c;SOC为全志的D1s&#xff0c;的核心板&#xff0c;手工焊接在白嫖的底板上&#xff08;此处感谢百问网老师的友情支持&#xff0c;手动狗头&#xff09;。在焊接完成后&#xff0c;进行点亮跑程序的时候&#xff0c;发现没有优雅…

Makefile静态库动态库的构建和链接之工程实用篇

静态库和动态库的构建和链接 现有C工程目录结构如下&#xff1a; add.h int add(int a, int b);add.cpp #include "add.h"int add(int a, int b) {return ab; }main.cpp #include <iostream> #include "add.h"int main() {std::cout << a…

GEE必须会教程—曾“几何”时(Geometry类型)

几何图形组成了世界万物&#xff0c;在数学史具有重要地位&#xff0c;将几何图形迁移到地理空间信息的处理上&#xff0c;我们我们得到就是研究区域的边界范围&#xff0c;因此&#xff0c;在学习矢量数据和栅格数据之前&#xff0c;我们有必要了解几何图形在GEE上的编辑。 1…

C语言——结构体——(第21篇)

坚持就是胜利 文章目录 一、结构体类型的声明1、结构的基础知识2、结构的声明3、结构成员的类型 二、结构体变量的定义和初始化结构体中包含结构体 三、结构体成员访问问题一&#xff1a;t.name "张三"&#xff0c;对吗&#xff1f;问题二&#xff1a;set_Stu(s);应…

C#与VisionPro联合开发——跳转页面

1、跳转页面并打开相机 From1 所有代码展示 using System; using System.IO; using System.Windows.Forms; //引入VisionPro命名空间 using Cognex.VisionPro;namespace ConnectCamera {public partial class Form1 : Form {public Form1() {InitializeComponent();}CogAcqFif…

Java核心-核心类与API(3)

话接上回&#xff0c;继续核心类与API的学习&#xff0c;这次介绍一下枚举类以及与系统、交互有关的类&#xff0c;需要了解并能使用即可。 一、枚举类 1、概述 枚举也称穷举&#xff0c;简单理解就是把所有可能一一列举出来&#xff08;穷尽所有可能&#xff09;。枚举是一…

前端学习——JS学习

文章目录 1. 定义变量&#xff0c;关键字 var、let、const2. 定义变量&#xff0c;数据类型3. 数组变量的操作4. 对象的操作5. JSON 字符串 1. 定义变量&#xff0c;关键字 var、let、const 这里主要是对var、let做比较 /** 1. var存在变量提升、let不存在变量提升 **/ cons…

【C语言基础】:操作符详解(一)

文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…

【域适应论文汇总】未完结

文章目录 DANN&#xff1a;Unsupervised Domain Adaptation by Backpropagation (2015)TADA&#xff1a;Transferable Attention for Domain Adaptation&#xff08;2019 AAAI&#xff09;1 局部注意力迁移&#xff1a;Transferable Local Attention2 全局注意力迁移&#xff1…

调度服务看门狗配置

查看当前服务器相关的sqlserver服务 在任务栏右键&#xff0c;选择点击启动任务管理器 依次点击&#xff0c;打开服务 找到sqlserver 相关的服务&#xff0c; 确认这些服务是启动状态 将相关服务在看门狗中进行配置 选择调度服务&#xff0c;双击打开 根据上面找的服务进行勾…

打开 Camera app 出图,前几帧图像偏暗、偏色该怎样去避免?

1、问题背景 使用的安卓平台&#xff0c;客户的应用是要尽可能快的获取到1帧图像效果正常的图片。 但当打开 camera 启动出流后&#xff0c;前3-5帧图像是偏暗、偏色的&#xff0c;如下图所示&#xff0c;是抓取出流的前25帧图像&#xff0c; 前3帧颜色是偏蓝的&#xff0c;…

vue2和vue3 setup beforecreate create生命周期时间比较

创建一个vue程序&#xff0c;vue3可以兼容Vue2的写法&#xff0c;很流畅完全没问题 写了一个vue3组件 <template><div></div> </template><script lang"ts"> import {onMounted} from vue export default{data(){return {}},beforeCr…