学习完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++ 并发编程后 手写线程池 最简单的线程池
目录 精简版注释: //线程安全的队列容器(精简版) 最简易可行的线程池(精简版) 详细版注释: //线程安全的队列容器(详细版) 最简易可行的线程池(详细版࿰…...
【Overload游戏引擎分析】编辑器对象鼠标拾取原理
Overload的场景视图区有拾取鼠标功能,单击拾取物体后会显示在Inspector面板中。本文来分析鼠标拾取这个功能背后的原理。 一、OpenGL的FrameBuffer 实现鼠标拾取常用的方式有两种:渲染id到纹理、光线投射求交。Overload使用的是渲染id到纹理,…...
【Spring内容进阶 | 第三篇】AOP进阶内容
前言: 在前面我们已经粗略的介绍了什么是AOP以及各种基础知识点,而本篇我们将聚焦于AOP的细节,详细的讲解一下AOP中的通知类型,通知顺序,切入点表达式以及连接点。通过对AOP的熟练掌握,我们可以快速编写出低…...
华为云ModelArts:引领AI艺术创作的未来,让人人都可以成为“艺术家”!
随着科技的飞速发展,艺术创作逐渐告别传统的画布和画笔,开始走向数字化、智能化的新时代。在这个蓬勃发展的领域中,华为云ModelArts以其强大的功能和出色的性能引领着AI艺术创作的未来。 华为云ModelArts是面向开发者的一站式AI开发平台,为机器学习与深度学习提供海量数据预处…...
Elasticsearch:如何从 Elasticsearch 集群中删除数据节点
Elasticsearch 集群通常包含多个节点,并且可能存在需要从集群中删除节点的情况。 应谨慎执行此过程,以确保数据的完整性和可用性。 在本文中,我们将引导你完成从 Elasticsearch 集群安全删除节点的步骤。 确保集群是绿色的 在尝试从 Elastic…...
长假回归,回顾一下所有的电商API接口
淘宝API接口 item_get 获得淘宝商品详情item_get_pro 获得淘宝商品详情高级版item_review 获得淘宝商品评论 获取测试keyitem_fee 获得淘宝商品快递费用item_password 获得淘口令真实urlitem_list_updown 批量获得淘宝商品上下架时间seller_info 获得淘宝店铺详情item_search…...
认识计算机主板
目录 定义主要部件简单图示 主要功能 定义 计算机主板(Motherboard)是计算机系统中的核心组件之一,也被称为系统板、主板或母板。它是一个电子电路板,用于连接和支持计算机的各种硬件组件,包括中央处理器(…...
PHP乱七八糟面试题
1、请解释PHP中的JWT是什么? JWT(JSON Web Token)是一种用于认证和授权的标准,可以在不同的系统之间安全地传递信息。 在PHP中,可以使用各种JWT库来生成和解析JWT,JWT包含了一些元数据和签名, …...
pom管理规范
0. 引言 在单机架构下,我们只需要将我们的依赖在pom中引入。但是过渡到微服务架构后,会涉及到多模块引用相同的依赖,多模版之间依赖的版本太过分散难以管理的问题。 这就需要我们利用maven中依赖传递的特性,结合dependencyManage…...
AI大模型的安全隐患问题与新兴Anthropic新势力涌动
引言: 无论从社会层面或技术层面,大模型的安全隐患都是一个不容小觑的话题。也正因此,ChatGPT 初兴起时,国内的 To C 大模型产品一时受阻。而尽管 9 月初第一批 8 家大模型通过备案,各家厂商对大模型的安全问题也不敢…...
slamplay:用C++实现的SLAM工具集
0. 项目简介 slamplay 是一个功能强大的工具集合,可用于开始使用 C 来玩和试验 SLAM。这是一项正在进行的工作。它在单个 cmake 框架中安装并提供一些最重要的功能 后端框架(g2o、gtsam、ceres、se-sync 等)、 前端工具(opencv、…...
IPT2602协议-USB 快速充电端口控制器
产品描述: IPT2602是一款USB端口快速充电协议控制芯片。IPT2602智能识别多种快速充电协议,对手机等受电设备进行快速充电。IPT2602根据受电设备发送的电压请求能够精确的调整VBUS输出电压,从而实现快速充电。 IPT2602在调整5V输出电压前会自动…...
Zotero 超好用插件的下载链接及配置方法(PDF-translate/ZotFile/茉莉花/Zotero Scihub)
目录 前言插件安装方法插件一:文献翻译插件(pdf-translate)插件二:文献附件管理(ZotFile)插件三:中文文献插件(茉莉花)插件四:Sci-Hub 自动下载文献ÿ…...
Titus网关中的缓存一致性机制
API网关引入缓存可以在不影响数据一致性的前提下,有效优化接口时延。本文介绍了Netflix在Titus网关上引入缓存的实践,比较了有无缓存对访问时延的影响。原文: Consistent caching mechanism in Titus Gateway 前言 Titus是Netflix的云容器运行时…...
flutter开发实战 - inappwebview设置cookie
flutter开发实战-inappwebview设置cookie 在使用inappwebview时候,需要设置cookie,这里记录一下 一、在initialUserScripts中设置cookie 在inappwebview中有一个initialUserScripts,可以初始化设置cookie等,我们可以通过该属性…...
零基础如何自学网络安全,基于就业前景全方位讲解,包教包会
你是否对网络空间安全充满好奇?想要解开网络世界神秘的面纱?你是否对黑客技术着迷?而找不到合适的学习途径?你是否遭到过各种各样的网络攻击,却因知识的匮乏束手无策? 那么接下来将为你全面介绍,…...
Java项目防止SQL注入的几种方案
目录 一、什么是SQL注入? 二、Java项目防止SQL注入方式 1、PreparedStatement防止SQL注入 2、mybatis中#{}防止SQL注入 3、对请求参数的敏感词汇进行过滤 4、nginx反向代理防止SQL注入 一、什么是SQL注入? SQL注入即是指web应用程序对用户输入数…...
Win11 安装安卓子系统方法教程
WIN11安装安卓子系统 准备工作下载安装安装完成使用adb连接子系统结束 准备工作 开启电脑中的 控制面板>>>>程序和功能>>启用或关闭Windows功能>>>找到“Hyper-V”,把勾都勾上,确定,完成安装,并重启电…...
golang pg 数据库不存在 就创建 --chatPGT
问:linkOrCreateDatabase(addr ), 函数执行 连接 pg数据库,若数据库 不存在就创建 gpt: 要在 Go 中连接到 PostgreSQL 数据库并在数据库不存在时创建数据库,你可以使用 github.com/lib/pq 包以及 database/sql 包。以下是一个示例࿱…...
VUE3照本宣科——eslint与prettier
VUE3照本宣科——eslint与prettier VUE3照本宣科系列导航 前言一、eslint1.配置文件2.配置规则3.忽略错误 二、prettier三、总结 VUE3照本宣科系列导航 1.VUE3照本宣科——认识VUE3 2.VUE3照本宣科——应用实例API与setup 3.VUE3照本宣科——响应式与生命周期钩子 4.VUE3照本宣…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
