C++多线程打工人

        为啥写这个,今天面试问到了~当时基于信号量写了一个单线程+无锁队列的实现,但是面试官实际想要的是多线程+条件变量实现的方式。

基本概念

        生产者消费者模型是一种常见的并发设计模式,用于处理生产者(生成数据)和消费者(处理数据)之间的协调问题。在多线程环境中,生产者和消费者可能运行在不同的线程中,因此需要同步机制来避免竞态条件和确保数据的一致性。        

        在生产者消费者模型中,生产者负责生成数据并将其放入一个共享的缓冲区,而消费者则从缓冲区中取出数据进行处理。共享缓冲区通常是有限大小的,这意味着生产者在缓冲区满时必须等待,而消费者在缓冲区空时也必须等待。

开搞

        C++中的生产者消费者模型通常依赖于线程库(如C++11标准中的线程库)和同步原语(如互斥锁、条件变量等)来实现。

        为了实现生产者消费者模型,我们需要以下组件:

  • 共享缓冲区:通常是一个队列,用于存储生产者生成的数据。
  • 互斥锁:用于保护共享缓冲区,确保同一时间只有一个线程可以访问缓冲区。
  • 条件变量:用于线程间的同步,允许线程在某个条件不满足时等待,并在条件满足时被唤醒。

以下是一个简单的生产者消费者模型实现示例:

首先是一个生产者消费者队列,提供了Produce和Consume能力,并维护了一个公共队列作为数据存储。

template <typename T>
class ProduceConsumeQueue {
public:ProduceConsumeQueue(uint32_t size) : sz_(size) {}void Produce(const T& data) {std::unique_lock<std::mutex> ulock(lock_);produce_cond_.wait(ulock, [this]() {return this->queue_.size() < sz_;});queue_.push(data);std::cout << "produce: " << data << std::endl;consume_cond_.notify_one();}T Consume() {std::unique_lock<std::mutex> ulock(lock_);consume_cond_.wait(ulock, [this]() {return !queue_.empty();});auto data = queue_.front();queue_.pop();std::cout << "consume: " << data << std::endl;produce_cond_.notify_one();return data;}private:std::mutex lock_;std::condition_variable produce_cond_;std::condition_variable consume_cond_;uint32_t sz_{0};std::queue<T> queue_;
};

        基于这个队列提供的生产消费能力,分别实现:

        一个资产阶级:        多个打工人

class Producer {
public:Producer() = default;void Init(std::shared_ptr<ProduceConsumeQueue<int> >& queue) {queue_ = queue;}void Produce() {int i = 0;while (true) {sleep(1);queue_->Produce(i++);}}private:std::shared_ptr<ProduceConsumeQueue<int> > queue_;
};class Consumer {
public:Consumer() = default;void Init(std::shared_ptr<ProduceConsumeQueue<int> >& queue) {queue_ = queue;}void Consume() {while (true) {auto val = queue_->Consume();}}private:std::shared_ptr<ProduceConsumeQueue<int> > queue_;
};int main() {auto pc_queue = std::make_shared<ProduceConsumeQueue<int> >(3);std::vector<Producer> producers(3);  // 打工人std::vector<Consumer> consumers(1);  // 资产阶级std::vector<std::thread> pthreads;std::vector<std::thread> cthreads;for (auto& p : producers) {p.Init(pc_queue);pthreads.emplace_back(std::thread(&Producer::Produce, &p));}for (auto& c : consumers) {c.Init(pc_queue);cthreads.emplace_back(std::thread(&Consumer::Consume, &c));}// joinpause();return 0;
}

 啪一下很快啊

code % g++ product_consume.cpp -std=c++17
code % ./a.out                           
produce: 0
consume: 0
produce: 0
consume: 0
produce: 0
consume: 0
produce: 1
consume: 1
produce: 1
consume: 1
produce: 1
consume: 1
^C
code % 

        上面的生产者消费者模型是一种简单而有效的并发编程模型,它具有以下优点:易于理解和实现、可以很好地解决多个线程之间的数据共享问题、可以提高程序的性能。但是,也存在一些缺点:可能存在饥饿问题(可以对生产者、消费者排队处理)。

        生产者消费者模型可以应用于各种场景,例如:多线程文件读写、多线程网络通信、多线程数据库访问等。

        上面调用std::condition_variable的wait操作的第二个参数是一个判断条件,收到条件信号的时候会判断是再判断是否满足条件,不满足会循环再等,省得我们手动再写一个循环判断了。
        在设计生产者消费者模型时,还需要考虑如何优雅地终止线程和处理异常情况,如join。

        附完整代码:https://github.com/Fireplusplus/Code_Cpp/blob/master/ProducerConsumer.cpp

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

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

相关文章

Rough.js:创建手绘、草图外观的图形

Rough.js 是一个小型的(<9kB gzipped)图形库&#xff0c;它可以让你以草图、手绘风格进行绘制。 该库定义了绘制直线、曲线、圆弧、多边形、圆和椭圆的基元。它还支持绘制 SVG 路径。 Rough.js 可以同时处理 Canvas 和 SVG。 安装 从npm安装&#xff1a; npm install --s…

【PDF密码】PDF文件为什么无法修改?为什么PDF文档不支持编辑?

pdf文件大家应该都经常接触&#xff0c;但是不知道大家会遇到这种情况&#xff1a;有些PDF文件打开之后无法编辑&#xff1f;是什么原因呢&#xff1f;今天我们来分析一下都是那些原因导致的。 首先我们可以考虑一下&#xff0c;PDF文件中的内容是否是图片&#xff0c;如果确认…

中国社科院大学与美国杜兰大学金融管理硕士项目——熬过寒冬,春日暖阳已不远

在金融领域&#xff0c;寒冬似乎成了无法避免的阶段。然而&#xff0c;对于那些坚守岗位的金融从业者来说&#xff0c;熬过寒冬并非无望。正如冬去春来&#xff0c;只要我们采取明智的策略&#xff0c;迈出坚定的步伐&#xff0c;春日的暖阳已在不远方照耀。社科院与美国杜兰大…

Vue2x的自定义指令和render函数使用自定义指令

在某些情况下&#xff0c;我们需要对底层DOM进行操作&#xff0c;而内置的指令不能满足需求&#xff0c;就需要自定义指令。一个自定义指令由一个包含类似组件的生命周期的钩子的对象来定义&#xff0c;钩子函数会接收到指令所绑定的元素作为参数。 定义指令 常用两种方式进行…

只有金蝶用户,才懂金蝶BI方案的含金量

资深金蝶系统用户都看得明明白白&#xff0c;金蝶系统侧重于企业资源的计划和管理&#xff0c;而当前企业数字化运营决策不仅需要高效合理的流程管理&#xff0c;更需要一套完善的数据分析方案&#xff08;金蝶BI方案&#xff09;&#xff0c;无缝对接金蝶系统&#xff0c;智能…

Spring MVC 的RequestMapping注解

RequestMapping注解 使用说明 作用&#xff1a;用于建立请求URL和处理请求方法之间的对应关系。 出现位置&#xff1a; 类上&#xff1a; 请求 URL的第一级访问目录。此处不写的话&#xff0c;就相当于应用的根目录。写的话需要以/开头。它出现的目的是为了使我们的 URL 可以…

Python类型转换,数据类型转换函数大全 与 strip()函数介绍

Python类型转换&#xff0c;数据类型转换函数大全 虽然 Python 是弱类型编程语言&#xff0c;不需要像 Java 或 C 语言那样还要在使用变量前声明变量的类型&#xff0c;但在一些特定场景中&#xff0c;仍然需要用到类型转换。 比如说&#xff0c;我们想通过使用 print() 函数…

006集 正则表达式 re 应用实例—python基础入门实例

正则表达式指预先定义好一个 “ 字符串模板 ” &#xff0c;通过这个 “ 字符串模 板” 可以匹配、查找和替换那些匹配 “ 字符串模板 ” 的字符串。 Python的中 re 模块&#xff0c;主要是用来处理正则表达式&#xff0c;还可以利用 re 模块通过正则表达式来进行网页数据的爬取…

LT8911EX LVDS 转 eDP

概述 Lontium LT8911EX 是 LVDS 至 eDP 转换器&#xff0c;具有单端口或双端口可配置 LVDS 接收器&#xff0c;具有 1 个时钟通道和多达 8 个数据通道&#xff0c;每个数据通道的最大工作速率为 1.2Gbps&#xff0c;最大输入带宽为 9.6Gbps。该转换器对输入LVDS数据进行反串行…

【小黑嵌入式系统第十四课】μC/OS-III程序设计基础(三)——信号量(任务同步资源同步)、事件标记组(与或多个任务)

上一课&#xff1a; 【小黑嵌入式系统第十三课】PSoC 5LP第二个实验——中断控制实验 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能 文章目录 1 信号量1.1 简介1.2…

学习笔记之——3D Gaussian Splatting源码解读

之前博客对3DGS进行了学习与调研 学习笔记之——3D Gaussian Splatting及其在SLAM与自动驾驶上的应用调研-CSDN博客文章浏览阅读450次。论文主页3D Gaussian Splatting是最近NeRF方面的突破性工作&#xff0c;它的特点在于重建质量高的情况下还能接入传统光栅化&#xff0c;优…

探索大模型时代下的文档识别与分析【GPT4-V带来的挑战与机遇】

中国图象图形学学会青年科学家会议是由中国图象图形学学会青年工作委员会发起的学术会议。本会议面向国际学术前沿与国家战略需求&#xff0c;致力于支持图象图形领域的优秀青年学者&#xff0c;为青年学者们提供学术交流与研讨的平台&#xff0c;促进学者之间的交流与合作。会…

深入理解C#中的引用类型、引用赋值以及 `ref` 关键字

深入理解C#中的引用类型、引用赋值以及 ref 关键字 在C#编程中&#xff0c;理解引用类型、引用赋值以及 ref 关键字的使用对于编写高效、可靠的代码至关重要。本文将深入探讨这些概念&#xff0c;帮助您更好地理解C#的工作原理。 引用类型简介 在C#中&#xff0c;所有的类型都…

MySQL的事务机制

一、事务机制简述 事务机制,避免写入直接操作数据文件&#xff1b;利用日志来实现间接写入&#xff0c;与事务有关的, redo日志与undo日志&#xff1b;sql语句操作记录复制到undo日志然后增删改查操作的结果会记录在redo日志&#xff0c;如果操作没有什么问题就把数据同步到数…

综合指南:理解气体检测仪的关键功能和单位换算

随着科技的飞速发展&#xff0c;气体检测仪在各行各业中的应用已十分普遍&#xff0c;其主要用途是检测环境中的气体浓度。 1、检测气体纯度 主要用于气体储罐、管道等储运设备中检测气体的纯度&#xff0c;一般都是专门针对高纯气体的浓度值进行检测&#xff0c;常见的如氩气…

C语言数组基础知识

目录 一维数组&#xff1a; 一维数组的创建&#xff1a; 一维数组的访问&#xff1a; 一维数组在内存中的存储&#xff1a; 二维数组&#xff1a; 二维数组的创建&#xff1a; 二维数组的初始化&#xff1a; 二维数组的使用&#xff1a; 二维数组在内存中的存储&#x…

上海晋名室外暂存柜助力石墨烯材料行业气瓶储存安全

近日上海晋名又有一台室外气瓶暂存柜项目通过验收&#xff0c;此次项目主要用于石墨烯材料行业气瓶的室外暂存。 用户单位创立于2017年&#xff0c;是一家从事石墨烯等新材料技术的科技型高新技术企业。 上海晋名作为一家专注工业安全防护领域&#xff0c;危险化学品安全储存…

RocketMQ Dashboard可视化工具

RocketMQ Dashboard 将 RocketMQ的相关指标展示在web页面 &#xff0c;支持以可视化工具代替 Topic 配置、Broker 管理等命令行操作。 官方文档地址&#xff1a;RocketMQ Dashboard | RocketMQ 目录 1.下载安装 1.1 系统要求&#xff1a; 1.2 源码安装 1.3 访问页面 2.功…

如何搭建开源知识库软件AFFiNE并实现公网环境远程协作【内网穿透】

目录 前言 1. 使用Docker安装AFFINE 2. 安装cpolar内网穿透工具 3. 配置AFFINE公网访问地址 4. 实现公网远程访问AFFINE 结语 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊如何搭建开源知识库软件AFFiNE并实现公网环境远程协作【内网穿…

借势API电商数据采集汇总分析

电商数据采集的网页抓取数据、淘宝、天猫、京东等平台的电商数据抓取&#xff0c;网页爬虫、采集网站数据、网页数据采集软件、python爬虫、HTM网页提取、APP数据抓包、APP数据采集、一站式网站采集技术、BI数据的数据分析、数据标注等成为大数据发展中的热门技术关键词。那么电…