当前位置: 首页 > news >正文

学习完C++ 并发编程后 手写线程池 最简单的线程池

目录

精简版注释:

//线程安全的队列容器(精简版)  

 最简易可行的线程池(精简版)

详细版注释:

//线程安全的队列容器(详细版) 

最简易可行的线程池(详细版)

ThreadRAII.h


参考:《C++并发编程实战 第二版》Anthony Willams著 吴天明 译

在学习完这本书后想要提高一下编码能力。

可以先参考精简版的注释,尝试写一写代码,感觉有难度的话就参考详细版。

具体代码和个人遇到的一些问题可以参考我的下一篇博客。

精简版注释:

//线程安全的队列容器(精简版)  

//实现线程安全的队列容器(通过封装一个queue)
//成员变量:
//      1.通过mutex互斥对pop、push操作加锁,从而实现“安全”
//      2.内部封装的queue,queue容器内部存储share_ptr,数据通过share_ptr间接存储好处:
//              将每个数据的share_ptr初始化放在push()中,wait_and_pop就算异常安全的
//              对share_ptr实例分配内存的操作可以脱离锁的保护,有利于增强性能
//      3.条件变量等待条件成立(pop之前必须先push)
//成员函数:
//      1.构造函数
//      2.push
//      3.pop 通过函数参数传递要pop的数据:
//              两种pop,try_pop立即返回,即使队列为空(通过返回值表示操作失败)
//              wait_and_pop 一直等到有数据才pop
//      4.通过返回值传递要pop的数据
//      5.empty
//
 

 最简易可行的线程池(精简版)

//成员变量:
//      1.监控异常的原子变量
//      2.线程安全的工作队列
//      3.工作线程
//      4.封装好的能够join线程的线程类
//      5.work_thread() 当线程池能正常工作时就一直循环执行任务

//公有成员:
//      1.构造函数
//      thread_pool():将监控异常的原子变量设置为false,
//              join_threads用工作线程vector初始化
//      {
//      }
//      2.析构函数
//      {
//       将原子变量设置为true,避免线程池销毁后,工作线程还在循环申请任务
//      }
//      3.提交线程函数(函数模板)
//      {
//              把待处理的任务(函数)提交给任务队列
//      }
//

详细版注释:

//线程安全的队列容器(详细版) 

//实现线程安全的队列容器(通过封装一个queue)
//成员变量:
//      1.通过mutex互斥对pop、push操作加锁,从而实现“安全”
//      2.内部封装的queue,queue容器内部存储share_ptr,数据通过share_ptr间接存储好处:
//              将每个数据的share_ptr初始化放在push()中,wait_and_pop就算异常安全的
//              对share_ptr实例分配内存的操作可以脱离锁的保护,有利于增强性能
//      3.条件变量等待条件成立(pop之前必须先push)
//成员函数:
//      1.构造函数
//      2.push{1.为数据创建share_ptr指针    //通过move移动操作降低开销2.互斥上锁3.队列push数据4.条件变量通知有数据}
//      3.pop 通过函数参数传递要pop的数据:
//           bool try_pop(T& value) //立即返回,即使队列为空(通过返回值表示操作失败){    //pop操作都是要操作队列的,所以一开始就要上锁,没有操作能提取到互斥之外1.互斥上锁2.判断是否为空队列 if(空) return false;else(不空) {1.队头数据传给value    //通过move移动操作降低开销2.队列pop3.return true;}}
//            void wait_and_pop(T& value) //一直等到有数据才pop{    //pop操作都是要操作队列的,所以一开始就要上锁,没有操作能提取到互斥之外1.互斥上锁;2.通过条件变量等待条件发生,通过lambda表达式保证即使被条件变量唤醒了,也要保证队列非空才能进行pop操作;3.对头数据传给value;4.队列pop               }
//      4.通过返回值传递要pop的数据:std::shared_ptr<T> try_pop(){    //pop操作都是要操作队列的,所以一开始就要上锁,没有操作能提取到互斥之外1.互斥上锁;2.判断是否为空队列 if(空) return nullptr;else(不空){1.临时变量取得队头数据2.队列pop3.return 临时变量}}std::shared_ptr<T> wait_and_pop(){    //pop操作都是要操作队列的,所以一开始就要上锁,没有操作能提取到互斥之外1.互斥上锁2.通过条件等待条件发生,通过lambda表达式保证即使被条件变量唤醒了,也要保证队列非空才能进行pop操作;3.临时变量取得对头数据4.队列pop5.return 临时变量}
//      5. bool empty() const{    //函数声明为const 要求将mutex 声明为mutable1.互斥上锁2.返回 封装队列的empty();}
//

最简易可行的线程池(详细版)

#ifndef _THREAD_POOL_EASY_HPP_
#define _THREAD_POOL_EASY_HPP_
#include "ThreadRAII" //join_threads
#include "threadsafe_queue"    //   
//最简单的线程池::工作线程数目固定,当有任务要处理时就把他放进任务队列
//所以需要一个任务队列,用threadsafe_queue来实现
//各线程从任务队列中领取任务
//工作线程存储在vector容器中,并被引用到join_threads中,进行统一的析构管理
//
//私有成员:
//      1.线程的启动可能抛出异常,所以需要一个原子变量进行标识,
//      当该变量false时,线程池正常工作
//              每当有异常抛出时,设置为true 
//              线程池析构时,也设置为true,
//              保证线程池析构后工作线程不会继续循环尝试从工作队列中获取任务
//      2.线程安全的工作队列
//      3.使用vector容器存放工作线程
//      4.封装好的能够join线程的线程类join_threads 里面存的是工作线程vector的整个引用 
//      5.work_thread() 当线程池能正常工作时就一直循环执行任务
//              {
//                      while(线程池正常工作)
//                      {
//                              临时变量用来接收任务
//                              if(工作队列能pop出任务)
//                                      执行任务;
//                              else 
//                                      将cpu时间让给其他线程;
//                      }
//              }
//公有成员:
//      1.构造函数
//      thread_pool():将监控异常的原子变量设置为false,
//              join_threads用工作线程vector初始化
//      {
//              通过std::thread::hardware_concurrency()取得最大线程数
//              try
//              { //线程启动可能抛出异常,所以用try catch包住
//                      for(最大线程数)
//                      {
//                              工作线程放到存放工作线程的vector里
//                      }
//              }
//              catch(...){
//                      出现异常将原子变量设置为true;
//                      throw;
//              }
//      }
//      2.析构函数
//      {
//       将原子变量设置为true,避免线程池销毁后,工作线程还在循环申请任务
//      }
//      3.提交线程函数(函数模板)
//      {
//              把待处理的任务(函数)提交给任务队列
//      }
//#endif

ThreadRAII.h

还需要封装thread类,使std::thread对象在所有路径皆不可联结:详细请参考本书第八章或effective modren C++ 条款37

#ifndef _THREADRAII_H_
#define _THREADRAII_H_//通过封装thread类,使std::thread对象在所有路径皆不可联结
// 详细参见 effective modren C++ 条款37
#include <vector>
#include <thread>
class join_threads
{private:std::vector<std::thread>& threads;public:explicit join_threads(std::vector<std::thread>& threads_):threads(threads_) {}~join_threads(){for(unsigned long i =0; i<threads.size(); i++){if(threads[i].joinable()){threads[i].join();}else{threads[i].detach();}}}
};
#endif

相关文章:

学习完C++ 并发编程后 手写线程池 最简单的线程池

目录 精简版注释&#xff1a; //线程安全的队列容器&#xff08;精简版&#xff09; 最简易可行的线程池&#xff08;精简版&#xff09; 详细版注释&#xff1a; //线程安全的队列容器&#xff08;详细版&#xff09; 最简易可行的线程池&#xff08;详细版&#xff0…...

【Overload游戏引擎分析】编辑器对象鼠标拾取原理

Overload的场景视图区有拾取鼠标功能&#xff0c;单击拾取物体后会显示在Inspector面板中。本文来分析鼠标拾取这个功能背后的原理。 一、OpenGL的FrameBuffer 实现鼠标拾取常用的方式有两种&#xff1a;渲染id到纹理、光线投射求交。Overload使用的是渲染id到纹理&#xff0c…...

【Spring内容进阶 | 第三篇】AOP进阶内容

前言&#xff1a; 在前面我们已经粗略的介绍了什么是AOP以及各种基础知识点&#xff0c;而本篇我们将聚焦于AOP的细节&#xff0c;详细的讲解一下AOP中的通知类型&#xff0c;通知顺序&#xff0c;切入点表达式以及连接点。通过对AOP的熟练掌握&#xff0c;我们可以快速编写出低…...

华为云ModelArts:引领AI艺术创作的未来,让人人都可以成为“艺术家”!

随着科技的飞速发展,艺术创作逐渐告别传统的画布和画笔,开始走向数字化、智能化的新时代。在这个蓬勃发展的领域中,华为云ModelArts以其强大的功能和出色的性能引领着AI艺术创作的未来。 华为云ModelArts是面向开发者的一站式AI开发平台,为机器学习与深度学习提供海量数据预处…...

Elasticsearch:如何从 Elasticsearch 集群中删除数据节点

Elasticsearch 集群通常包含多个节点&#xff0c;并且可能存在需要从集群中删除节点的情况。 应谨慎执行此过程&#xff0c;以确保数据的完整性和可用性。 在本文中&#xff0c;我们将引导你完成从 Elasticsearch 集群安全删除节点的步骤。 确保集群是绿色的 在尝试从 Elastic…...

长假回归,回顾一下所有的电商API接口

淘宝API接口 item_get 获得淘宝商品详情item_get_pro 获得淘宝商品详情高级版item_review 获得淘宝商品评论 获取测试keyitem_fee 获得淘宝商品快递费用item_password 获得淘口令真实urlitem_list_updown 批量获得淘宝商品上下架时间seller_info 获得淘宝店铺详情item_search…...

认识计算机主板

目录 定义主要部件简单图示 主要功能 定义 计算机主板&#xff08;Motherboard&#xff09;是计算机系统中的核心组件之一&#xff0c;也被称为系统板、主板或母板。它是一个电子电路板&#xff0c;用于连接和支持计算机的各种硬件组件&#xff0c;包括中央处理器&#xff08;…...

PHP乱七八糟面试题

1、请解释PHP中的JWT是什么&#xff1f; JWT&#xff08;JSON Web Token&#xff09;是一种用于认证和授权的标准&#xff0c;可以在不同的系统之间安全地传递信息。 在PHP中&#xff0c;可以使用各种JWT库来生成和解析JWT&#xff0c;JWT包含了一些元数据和签名&#xff0c; …...

pom管理规范

0. 引言 在单机架构下&#xff0c;我们只需要将我们的依赖在pom中引入。但是过渡到微服务架构后&#xff0c;会涉及到多模块引用相同的依赖&#xff0c;多模版之间依赖的版本太过分散难以管理的问题。 这就需要我们利用maven中依赖传递的特性&#xff0c;结合dependencyManage…...

AI大模型的安全隐患问题与新兴Anthropic新势力涌动

引言&#xff1a; 无论从社会层面或技术层面&#xff0c;大模型的安全隐患都是一个不容小觑的话题。也正因此&#xff0c;ChatGPT 初兴起时&#xff0c;国内的 To C 大模型产品一时受阻。而尽管 9 月初第一批 8 家大模型通过备案&#xff0c;各家厂商对大模型的安全问题也不敢…...

slamplay:用C++实现的SLAM工具集

0. 项目简介 slamplay 是一个功能强大的工具集合&#xff0c;可用于开始使用 C 来玩和试验 SLAM。这是一项正在进行的工作。它在单个 cmake 框架中安装并提供一些最重要的功能 后端框架&#xff08;g2o、gtsam、ceres、se-sync 等&#xff09;、 前端工具&#xff08;opencv、…...

IPT2602协议-USB 快速充电端口控制器

产品描述&#xff1a; IPT2602是一款USB端口快速充电协议控制芯片。IPT2602智能识别多种快速充电协议&#xff0c;对手机等受电设备进行快速充电。IPT2602根据受电设备发送的电压请求能够精确的调整VBUS输出电压&#xff0c;从而实现快速充电。 IPT2602在调整5V输出电压前会自动…...

Zotero 超好用插件的下载链接及配置方法(PDF-translate/ZotFile/茉莉花/Zotero Scihub)

目录 前言插件安装方法插件一&#xff1a;文献翻译插件&#xff08;pdf-translate&#xff09;插件二&#xff1a;文献附件管理&#xff08;ZotFile&#xff09;插件三&#xff1a;中文文献插件&#xff08;茉莉花&#xff09;插件四&#xff1a;Sci-Hub 自动下载文献&#xff…...

Titus网关中的缓存一致性机制

API网关引入缓存可以在不影响数据一致性的前提下&#xff0c;有效优化接口时延。本文介绍了Netflix在Titus网关上引入缓存的实践&#xff0c;比较了有无缓存对访问时延的影响。原文: Consistent caching mechanism in Titus Gateway 前言 Titus是Netflix的云容器运行时&#xf…...

flutter开发实战 - inappwebview设置cookie

flutter开发实战-inappwebview设置cookie 在使用inappwebview时候&#xff0c;需要设置cookie&#xff0c;这里记录一下 一、在initialUserScripts中设置cookie 在inappwebview中有一个initialUserScripts&#xff0c;可以初始化设置cookie等&#xff0c;我们可以通过该属性…...

零基础如何自学网络安全,基于就业前景全方位讲解,包教包会

你是否对网络空间安全充满好奇&#xff1f;想要解开网络世界神秘的面纱&#xff1f;你是否对黑客技术着迷&#xff1f;而找不到合适的学习途径&#xff1f;你是否遭到过各种各样的网络攻击&#xff0c;却因知识的匮乏束手无策&#xff1f; 那么接下来将为你全面介绍&#xff0c…...

Java项目防止SQL注入的几种方案

目录 一、什么是SQL注入&#xff1f; 二、Java项目防止SQL注入方式 1、PreparedStatement防止SQL注入 2、mybatis中#{}防止SQL注入 3、对请求参数的敏感词汇进行过滤 4、nginx反向代理防止SQL注入 一、什么是SQL注入&#xff1f; SQL注入即是指web应用程序对用户输入数…...

Win11 安装安卓子系统方法教程

WIN11安装安卓子系统 准备工作下载安装安装完成使用adb连接子系统结束 准备工作 开启电脑中的 控制面板>>>>程序和功能>>启用或关闭Windows功能>>>找到“Hyper-V”&#xff0c;把勾都勾上&#xff0c;确定&#xff0c;完成安装&#xff0c;并重启电…...

golang pg 数据库不存在 就创建 --chatPGT

问&#xff1a;linkOrCreateDatabase(addr ), 函数执行 连接 pg数据库&#xff0c;若数据库 不存在就创建 gpt: 要在 Go 中连接到 PostgreSQL 数据库并在数据库不存在时创建数据库&#xff0c;你可以使用 github.com/lib/pq 包以及 database/sql 包。以下是一个示例&#xff1…...

VUE3照本宣科——eslint与prettier

VUE3照本宣科——eslint与prettier VUE3照本宣科系列导航 前言一、eslint1.配置文件2.配置规则3.忽略错误 二、prettier三、总结 VUE3照本宣科系列导航 1.VUE3照本宣科——认识VUE3 2.VUE3照本宣科——应用实例API与setup 3.VUE3照本宣科——响应式与生命周期钩子 4.VUE3照本宣…...

【谷粒学院】Maven加载问题

问题 maven加载项目时候&#xff0c;默认不会加载src-java文件夹里面xml类型文件的 解决方案 直接赋值xml文件到target目录通过配置实现 &#xff08;1&#xff09;在pom.xml文件中配置 <!-- 项目打包时会将java目录中的*.xml文件也进行打包 --> <build><re…...

PostgreSQL数据库中实现字段递增

在 PostgreSQL 中&#xff0c;可以使用序列&#xff08;sequence&#xff09;来实现字段的递增。序列是一种特殊的对象&#xff0c;用于生成唯一的递增数字。 首先&#xff0c;您需要创建一个序列对象。可以使用以下命令创建一个名为 "my_sequence" 的序列&#xff…...

深度学习——深度学习计算二

深度学习——深度学习计算二 文章目录 前言三、延后初始化四、自定义层4.1. 不带参数的层4.2. 带参数的层 五、读写文件5.1. 加载和保存张量5.2. 加载和保存模型参数 六、GPU6.1. 计算设备6.2. 张量与GPU6.3. 神经网络与GPU 总结 前言 延续上一章的学习&#xff0c;本章继续记…...

HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Badge

可以附加在单个组件上用于信息标记的容器组件。该组件从API Version 7开始支持。 支持单个子组件。子组件类型&#xff1a;系统组件和自定义组件&#xff0c;支持渲染控制类型&#xff08;if/else、ForEach和LazyForEach&#xff09;。 一、接口 方法1&#xff1a; Badge(value…...

在Flink中集成和使用Hudi

本文介绍在Flink 中集成和使用Hudi。介绍Flink如何将Streaming引入Hudi。在Hudi上使用Flink,并学习Flink读写Hudi的不同模式: Flink SQL客户端写入:Flink SQL客户端写入(读取)Hudi。 配置:对于全局配置,通过$FLINK_HOME/conf/FLINK-conf.yaml进行设置。对于每个作业配置…...

docker搭建Jenkins及基本使用

1. 搭建 查询镜像 docker search jenkins下载镜像 docker pull jenkins/jenkins启动容器 #创建文件夹 mkdir -p /home/jenkins_home #权限 chmod 777 /home/jenkins_home #启动Jenkins docker run -d -uroot -p 9095:8080 -p 50000:50000 --name jenkins -v /home/jenkins_home…...

CSS初体验

目录 一、CSS初体验 二、CSS引入方式 三、选择器 3.1 标签选择器 3.2 类选择器 3.3 id选择器 3.4 通配符选择器 四、盒子尺寸和背景色 五、文字控制属性 5.1 字体大小 5.2 字体样式(是否倾斜) 5.3 行高 5.3.1 单行文字垂直居中 5.4 字体族 5.5 font复合属性 5.…...

python性能分析

基于cProfile统计函数级的时延&#xff0c;生成排序列表、火焰图&#xff0c;可以快速定位python代码的耗时瓶颈。参考如下博文结合实操&#xff0c;总结为三步&#xff1a; 使用 cProfile 和火焰图调优 Python 程序性能 - 知乎本来想坐下来写篇 2018 年的总结&#xff0c;仔细…...

苹果手机怎么备份所有数据?2023年iPhone 15数据备份常用的3种方法!

当苹果手机需要进行刷机、恢复出厂设置、降级iOS系统等操作时&#xff0c;我们需要将自己的iPhone数据提前进行备份。 特别是在苹果发布新iOS系统时&#xff0c;总有一些小伙伴因为升降级系统&#xff0c;而导致了重要数据的丢失。 iPhone中储存着重要的照片、通讯录、文件等数…...

【RV1103】如何新增一个新板级配置

文章目录 新建一个板级配置文件 新建一个板级配置文件 我的目标 通过./build.sh lunch 来选择我的板子配置。 在目录sdk/project/cfg目录下新建一个xxxx.mk文件&#xff0c;文件名字格式如下&#xff1a; BoardConfig-"启动介质"-"电源方案"-"硬件…...

如何做网站容易收录/百度推广一条资源多少钱

概述scanf()是C语言中的一个输出函数。与printf函数一样&#xff0c;都被声明在头文件stdio.h里&#xff0c;因此在使用scanf函数时要加上#include 。(在有一些实现中&#xff0c;printf函数与scanf函数在使用时可以不使用预编译命令#include 。)它是格式输入函数&#xff0c;即…...

建设网站方面的证书/如何网上销售自己的产品

用xml格式保存各种资料,包括希望公布的资料,如个人求职资料,以及希望注册时候使用的资料,到别的网站注册的时候可以直接提供个人帐号来注册,不需填太多资料.类似passport,但是会丰富很多.可以提供信用评价等等.可以加入更多相关功能.转载于:https://www.cnblogs.com/liugod/arc…...

wordpress 崩溃/免费发帖论坛大全

(1)自主式作业(提交截止时间为12月24日)由系统随机抽题的自主式作业&#xff0c;占总成绩的20%。学生登录面向学生自主学习的高级语言能力测试平台(SSE)&#xff0c;自主选择知识点和难度系数&#xff0c;平台自动从后台的题库系统中随机抽取相应知识点和难度系数的题目给学生&…...

网站seo公司/郑州网站策划

将图片转化为Base64字符串的流程是&#xff1a;首先使用BinaryFormatter将图片文件序列化为二进制数据&#xff0c;然后使用Convert类的ToBase64String方法。将Base64字符串转换为图片的流程正好相反&#xff1a;使用Convert类的FromBase64String得到图片文件的二进制数据&…...

东莞企业网站建设价格/企业网络营销策略分析案例

关于cmake的安装&#xff0c;CMakeLists.txt的语法规则&#xff0c;CMakeLists.txt的各种配置选项等复杂而专业的知识&#xff0c;限于本人能力&#xff0c;这里不再说明演示使用glibc2.0库一 项目目录laolanglaolang-Lenovo-G470:~/code/cmake/eclipse/HelloCMake$ tree.├──…...

网站增长期怎么做/推广平台都有哪些

在centos下要剪切文件或者文件夹的时候&#xff0c;一般都是使用的mv命令。 例如要移动a文件到b目录下。操作如下&#xff1a; #假设a和b处于同一级别的目录下 mv a b/ 如果要同时移动多个文件或者文件夹呢&#xff1f; 其实用的也是mv命令。 具体参数用的是-t 查看帮助解…...