C++ 实现多线程的生产者(producer) - 消费者(consumer) 模型

1. 模型介绍:

生产者消费者模型是操作系统中的一种并发编程模型,用于解决生产者和消费者之间的数据共享和同步问题。
在该模型中,生产者负责生成数据,并将数据放入一个有限的缓冲区中,而消费者则从缓冲区中取出数据进行处理。
两者之间通过共享的缓冲区进行通信。

2. 模型实现的要素:

为了实现正确的数据传输和同步,需要维护以下几个要素:

  • 缓冲区:用来存放生产者生成的数据。其大小可能是固定的或动态调整的。
  • 生产者:根据一定规则生成数据,并将数据放入缓冲区中。如果缓冲区已满,则需要等待消费者取出部分数据才能继续生产。
  • 消费者:从缓冲区中取出数据,并进行相应处理。如果缓冲区为空,则需要等待生产者放入新的数据才能继续消费。
  • 同步机制:用于保证生产者和消费者之间的顺序执行和互斥访问。常见的同步机制包括信号量、互斥锁、条件变量等。

在实际应用中,可以采用多线程或多进程来实现生产者消费者模型。多线程方案中,可以使用线程间共享的全局变量作为缓冲区,并利用互斥锁和条件变量来实现线程间的同步。多进程方案中,可以使用进程间共享的内存或文件来作为缓冲区,并利用信号量等机制来实现进程间的同步。

生产者消费者模型能够有效地解耦生产者和消费者之间的耦合关系,提高系统的并发性和吞吐量。然而,需要注意的是,在设计和实现过程中,需要考虑线程安全、死锁、饥饿等问题。同时,根据具体情况选择适当的同步机制和缓冲区大小也是非常重要的。

3. 经典的库和框架使用

生产者消费者模型来实现并发编程和数据处理。以下是其中一些常见的例子:

  • Java中的BlockingQueue:Java标准库提供了BlockingQueue接口,它实现了生产者消费者模型。生产者可以将数据放入队列中,而消费者可以从队列中取出数据进行处理。BlockingQueue提供了阻塞的插入和移除方法,确保当队列已满或为空时,调用线程会被阻塞。
  • Python中的queue模块:Python标准库中的queue模块提供了多种队列实现,包括FIFO队列(Queue)、LIFO队列(LifoQueue)和优先级队列(PriorityQueue)。这些队列都可以用于实现生产者消费者模型,并提供了多线程安全的操作方法。
  • POSIX线程库(pthread):POSIX线程库是一套用于操作系统级线程编程的标准接口。它提供了互斥锁(mutex)、条件变量(condition variable)等同步机制,可以通过这些机制来实现生产者消费者模型。
  • Apache Kafka:Apache Kafka是一个分布式流处理平台,广泛应用于大规模数据处理和消息传递场景。Kafka使用基于生产者消费者模型的消息队列来处理高吞吐量的流式数据。生产者将数据写入Kafka的主题(topic),而消费者从主题中读取和处理数据。
  • RabbitMQ:RabbitMQ是一个开源的消息队列中间件,支持多种消息传递协议。它使用生产者消费者模型来实现可靠的消息传递和异步通信。生产者将消息发送到RabbitMQ的交换机(exchange),而消费者从队列中接收和处理消息。

这些库和框架提供了一种方便而可靠的方式来实现生产者消费者模型,简化了并发编程和数据处理的复杂性。可以根据具体需求选择合适的库来实现并发任务和数据流处理。

4. C++ 代码实现

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>class ITask {
public:virtual void execute() = 0;virtual bool isLast() const = 0;
};std::mutex mutexLock;
std::condition_variable condVar;void producer(std::queue<std::shared_ptr<ITask>>& dataQueue)
{for (int i = 0; i < 10; ++i){std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Simulate some work// Create and enqueue a new taskstd::shared_ptr<ITask> task = std::make_shared<MyTask>(i);std::lock_guard<std::mutex> lock(mutexLock);dataQueue.push(task);std::cout << "Produced: " << i << std::endl;condVar.notify_one();}
}void consumer(std::queue<std::shared_ptr<ITask>>& dataQueue)
{while (true){std::unique_lock<std::mutex> lock(mutexLock);if (condVar.wait_for(lock, std::chrono::milliseconds(1000), [&dataQueue] { return !dataQueue.empty(); })){std::shared_ptr<ITask> task = dataQueue.front();dataQueue.pop();lock.unlock();// Execute the tasktask->execute();if (task->isLast())break;}else{// Timeout occurred, do something else or exitlock.unlock();std::cout << "Consumer timed out." << std::endl;break;}}
}class MyTask : public ITask {
private:int data;public:MyTask(int d) : data(d) {}void execute() override {std::cout << "Consumed: " << data << std::endl;}bool isLast() const override {return data == 9;}
};int main_()
{std::queue<std::shared_ptr<ITask>> dataQueue;// Start producer and consumer in separate threadsstd::thread producerThread(producer, std::ref(dataQueue));std::thread consumerThread(consumer, std::ref(dataQueue));producerThread.join();consumerThread.join();
}

5. 代码详解:

  • 抽象出 ITask 类,用户可以继承实现不同任务;
  • 线程执行 producer 函数,生产任务放到队列中;
  • 线程执行 consumer 函数,从队列中取任务,执行;
  • 主线程等待任务完全完成;

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

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

相关文章

网上零食销售系统

技术架构&#xff1a; Servlet MySQL JSP 功能描述&#xff1a; 1.浏览商品 &#xff08;1&#xff09; 商品详细资料 &#xff08;2&#xff09; 商品编号 2.订购商品 3.购物车 4.用户信息维护 &#xff08;1&#xff09; 用户注册 &#xff08;2&#xff09; 用户…

04-Seata修改通信端口

基于docker环境部署下&#xff0c;可以翻看专栏之前的文章 配置文件 /home/server/seata/resources/application.yml 默认${server.port} 1000 1、修改服务端(TC)配置 seata:server:service-port: 7090 2、修改映射端口 在启动脚本中修改映射端口 docker run -id --nam…

嵌入式——实时时钟(RTC)

目录 一、初识RTC 1.简介 2.特性 3.后备寄存器和RTC寄存器特性 二、RTC组成 1.相关寄存器 &#xff08;1&#xff09;控制寄存器高位&#xff08;RTC_CRH&#xff09; &#xff08;2&#xff09;控制寄存器低位&#xff08;RTC_CRL&#xff09; &#xff08;3&#xf…

『建议收藏』OpenAI官方出的Prompt提示词教程中文版来了!

一些结论 六大策略: 写清晰的指令 提供参考文本 将复杂任务分解为更简单的子任务 给模型时间“思考” 使用外部工具 系统性测试变化 提高结果质量的六大策略 写清晰的指令 这些模型无法读懂你的想法。如果输出过长&#xff0c;要求简短回复&#xff1b;如果输出过于简单…

Redis客户端之Redisson(二)Redisson组件

Redisson的几个常用客户端 一、RedissonClient 1、创建 通过Config对象配置RedissonClient所需要的参数&#xff0c;然后获取RedissonClient对象即可。 Config config new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonC…

【python】argparse解析参数的过程

python基础知识 python文件解析if __name__ __main__的作用import到底导入了什么&#xff1f;argparse解析命令行参数的过程 python文件解析 Python和C语言的编译、执行过程有很大区别。我们先回顾一下c语言的执行过程&#xff0c;首先代码文件要编译&#xff0c;编译通过&am…

【C++杂货铺】详解类和对象 [上]

博主&#xff1a;代码菌-CSDN博客 专栏&#xff1a;C杂货铺_代码菌的博客-CSDN博客 目录 &#x1f308;前言&#x1f308; &#x1f4c1; 面向对象语言的特性 &#x1f4c1; 类 &#x1f4c2; 概念 &#x1f4c2; 定义 &#x1f4c1; 访问限定符 &#x1f4c2;分类 &#x…

《WebKit 技术内幕》学习之十五(1):Web前端的未来学习

1 趋势 说到Web方面的趋势&#xff0c;特别是HTML5获得的巨大发展&#xff0c;W3C和WHATWG等组织正在不停地推动规范的演进和引入新的规范&#xff0c;这一举动必将极大地推动Web前端的发展。就目前Web前端来说&#xff0c;各种类型的技术非常多&#xff0c;极容易引起大家的误…

CMake 完整入门教程(一)

1 前言 每一次学习新东西都是很有乐趣的&#xff0c;虽然刚开始会花费时间用来学习&#xff0c;但是实践证明&#xff0c;虽然学习新东西可能会花费一些时间&#xff0c;但是它们带来的好处会远远超过这些花费的时间。学习新东西是值得的&#xff0c;也是很有乐趣的。 网络上…

【K8S 云原生】K8S的图形化工具——Rancher

目录 一、rancher概述 1、rancher概念 2、rancher和K8S的区别&#xff1a; 二、实验 1、安装部署 2、给集群添加监控&#xff1a; 3、创建命名空间&#xff1a; 4、创建deployment&#xff1a; 5、创建service&#xff1a; 6、创建ingress&#xff1a; 7、创建hpa 8…

基于高精度YOLOv8开发构建公共场景下行人人员姿态估计分析识别系统

姿态估计&#xff08;PoseEstimation&#xff09;在我们前面的相关项目中涉及到的并不多&#xff0c;CV数据场景下主要还是以目标检测、图像识别和分割居多&#xff0c;最近正好项目中在使用YOLO系列最新的模型开发项目&#xff0c;就想着抽时间基于YOLOv8也开发构建实现人体姿…

知识笔记(九十七)———什么是实体符???

在HTML中&#xff0c;有些字符无法直接在文本中输入&#xff0c;因为它们是HTML语言的保留字符&#xff0c;如小于号&#xff08;<&#xff09;、大于号&#xff08;>&#xff09;、&符号&#xff08;&&#xff09;等。为了将这些字符显示在网页上&#xff0c;需…

[UI5 常用控件] 02.Title,Link,Label

文章目录 前言1. Title1.1 结合Panel1.2 结合Table1.3 Title里嵌套Link 2. Link3. Label3.1 普通用法3.2 在Form里使用 前言 本章节记录常用控件Title,Link,Label。 其路径分别是&#xff1a; sap.m.Titlesap.m.Linksap.m.Label 1. Title Title可以结合其他控件一起使用 1.…

总结红包雨项目的所有代码,包括添加图片,分享按钮,红包雨,用户是否有抽奖逻辑判断

整体实现效果: 需要用的图片: html: <body><div id"app"><!-- <div class"share-box"><img src"./share_box.png" alt"share-button"></div> --><!-- img图片 --><div class"gif-…

DNS解析记录类型

在数字化时代&#xff0c;理解DNS&#xff08;域名系统&#xff09;解析的各种记录类型对于任何网络专业人士来说都是至关重要的。DNS作为互联网的基石&#xff0c;其记录类型的多样性和复杂性使得网络通信既高效又安全。以下是对DNS记录类型的详细解读。 A记录&#xff08;Ad…

axios结合ts使用,取消请求,全局统一获取数据,抛出错误信息

通常在开发时&#xff0c;后端向前端返回的数据可以如下&#xff1a; 1 使用restful api充分利用http状态码&#xff0c;然后在data中追加code字段&#xff0c;请求成功返回200,请求失败返回404,401,500等状态码&#xff0c;并且在code字段中给出详细的字符串信息2 再包一层&a…

JVM基础知识汇总篇

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…

【力扣每日一题】力扣2865美丽塔I

题目来源 力扣2865美丽塔I 题目概述 给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。 你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i &#xff0c;高度为 heights[i] 。 如果以下条件满足&#xff0c;我们称这些塔是 美丽 的&#xff1a; 1 < heights…

翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一

随着 OpenAI 在多模态方面的最新进展&#xff0c;想象一下将这种能力与视觉理解相结合。 现在&#xff0c;您可以在 Streamlit 应用程序中使用 GPT-4 和 Vision&#xff0c;以&#xff1a; 从草图和静态图像构建 Streamlit 应用程序。帮助你优化应用的用户体验&#xff0c;包…

《合成孔径雷达成像算法与实现》Figure5.18

clc clear close all距离向参数 R_eta_c 20e3; % 景中心斜距 Tr 25e-6; % 发射脉冲时宽 Kr 0.25e12; % 距离向调频率 Fr 7.5e6; % 距离向采样率 Nrg 256; % 距离线采样点数 Bw abs(Kr*Tr); …