[C++ 中的生产者-消费者模型]

news/2023/11/28 18:43:51

在多线程编程中,生产者-消费者模型是一个常见的设计模式,用于协调不同线程之间的数据共享和处理。本文将介绍如何在C++中实现生产者-消费者模型,以及一些相关的概念和最佳实践。

什么是生产者-消费者模型?

生产者-消费者模型是一种并发编程模式,通常涉及两种不同类型的线程:生产者和消费者。生产者负责生成数据,并将其放入共享的缓冲区中,而消费者负责从缓冲区中取出数据并进行处理。这种模型的主要目标是实现线程之间的协同工作,以确保数据安全和高效的数据传输。

实现生产者-消费者模型

在C++中,可以使用线程和互斥锁(mutex)、条件变量(condition variable)来实现生产者-消费者模型。下面是一个简单的示例代码:

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>std::queue<int> buffer;            // 共享的缓冲区,用于生产者和消费者之间的数据传递
std::mutex mtx;                    // 互斥锁,用于保护对缓冲区的并发访问
std::condition_variable cv;        // 条件变量,用于通知消费者新数据的可用性// 生产者函数
void producer() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(200));  // 模拟生产延迟int data = i;  // 生产数据{std::unique_lock<std::mutex> lock(mtx);  // 获取互斥锁buffer.push(data);  // 将数据放入缓冲区}cv.notify_one();  // 通知等待的消费者数据已准备好}
}// 消费者函数
void consumer() {for (int i = 0; i < 10; ++i) {int data;{std::unique_lock<std::mutex> lock(mtx);  // 获取互斥锁cv.wait(lock, [] { return !buffer.empty(); });  // 等待数据可用data = buffer.front();  // 从缓冲区中取出数据buffer.pop();  // 从缓冲区中移除数据}std::cout << "Consumed: " << data << std::endl;  // 处理数据}
}int main() {std::thread producerThread(producer);  // 创建生产者线程std::thread consumerThread(consumer);  // 创建消费者线程producerThread.join();  // 等待生产者线程结束consumerThread.join();  // 等待消费者线程结束return 0;
}

在上面的示例中,我们使用了一个std::queue作为共享缓冲区,std::mutex用于保护缓冲区的访问,std::condition_variable用于在生产者生成数据时通知消费者,并在缓冲区为空时阻塞消费者。

最佳实践

  1. 线程安全性:确保在访问共享数据时使用适当的同步机制,如互斥锁和条件变量,以防止竞态条件。

  2. 缓冲区大小:根据应用程序需求和系统资源,选择合适的缓冲区大小。

  3. 错误处理:处理可能的异常情况,如缓冲区溢出或下溢。

  4. 线程管理:确保适当管理和协调生产者和消费者线程的启动和结束。

  5. 性能优化:考虑使用更高级的并发工具,如C++11中引入的std::asyncstd::future,以提高性能。

生产者-消费者模型是一种强大的多线程编程模式,可以帮助解决数据共享和线程同步的问题。通过使用C++的标准库,您可以轻松地实现这一模式,并确保程序的可靠性和性能。不过,务必小心处理同步和错误处理,以确保应用程序的稳定性。


http://www.ppmy.cn/news/1147912.html

相关文章

【Qt之信号和槽】对象多层嵌套后,高效使用信号和槽

抛出问题 Qt的信号槽机制非常牛逼&#xff0c;也是Qt的独特的核心功能之一。 有时候在很多窗体中传递信号来实现更新或者处理&#xff0c;如果窗体层级比较多&#xff0c;比如窗体A的父类是窗体B&#xff0c;窗体B的父类是窗体C&#xff0c;窗体C有个子窗体D&#xff0c;如果窗…

leetcode35. Search Insert Position

文章目录 一、题目二、题解 一、题目 Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You must write an algorithm with O(log n) r…

微信小程序 在bindscroll事件中监听scroll-view滚动到底

scroll-view其实提供了一个 bindscrolltolower 事件 这个事件的作用是直接监听scroll-view滚动到底部 但是 总有不太一样的情况 公司的项目 scroll-view 内部 最下面有一个 类名叫 bottombj 的元素 我希望 滚动到这个 bottombj 上面的时候就开始加载滚动分页 简单说 bottombj这…

3、TCP状态

TCP状态 1、TCP通信时序 三次握手成功后&#xff0c;服务器和客户端进入了状态ESTABLISHED 当处于Time_WAIT状态后&#xff0c;不会马上变成CLOSE状态&#xff0c;会经历2MSL&#xff08;约40秒&#xff09;&#xff0c;之后才会进入CLOSE状态。 总结&#xff1a; 主动发起…

04_学习springdoc与oauth结合_简述

文章目录 1 前言2 基本结构3 需要做的配置 简述4 需要做的配置 详述4.1 backend-api-gateway 的配置4.1.1 application.yml 4.2 backend-film 的配置4.2.1 pom.xml 引入依赖4.2.2 application.yml 的配置4.2.3 Spring Security 资源服务器的配置类 MyResourceServerConfig4.2.4…

获取操作系统信息服务器信息JVM信息cpu内存磁盘信息

1.添加依赖 <dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId><version>5.6.0</version> </dependency>

贪心+分类讨论完整性:ARC123C

https://www.luogu.com.cn/problem/AT_arc123_c 场上就简单猜了个结论&#xff0c;[1,3]>1, [4,6]>2, [7,9]>3&#xff0c;0>4&#xff0c;若存在1则此时必须为1个数&#xff0c;否则为4。存在2则必须<2&#xff0c;否则为4. 但我没对4进行完整讨论。如果4个数…

【Java学习之道】继承与多态

引言 本文将介绍面向对象编程的核心概念——继承与多态。对于初学者来说&#xff0c;掌握这些基本概念是迈向Java高手的第一步。接下来&#xff0c;让我们一起揭开继承与多态的神秘面纱&#xff0c;感受它们的魅力吧&#xff01; 一、继承 继承是面向对象编程的一个重要特性…

《RISC-V体系结构编程与实践》的benos_payload程序——mysbi跳转到benos分析

1、benos_payload.bin结构分析 韦东山老师提供的开发文档里已经对程序的结构做了分析&#xff0c;这里不再赘述&#xff0c;下面是讨论mysbi跳转到benos的问题&#xff1b; 2、mysbi跳转到benos的代码 3、跳转产生的疑问 我认为mysbi.bin最后跳转到0x22000地址处执行&#xff0…

腾讯云我的世界mc服务器配置选择和价格表

开Minecraft我的世界服务器配置怎么选择&#xff1f;10人以内玩2核4G就够用了&#xff0c;开我的世界服务器选择轻量应用服务器就够了&#xff0c;腾讯云轻量应用服务器2核2G3M带宽轻量服务器一年95元&#xff0c;活动&#xff1a;txyfwq.com/go/tencent 轻量CPU采用至强白金处…

xss漏洞及排查

xss漏洞 举个例子说明&#xff0c;假设server端有这么一个rest接口&#xff08;我们用flask实现&#xff09;&#xff1a; app.route(/test) def hello_world():name request.args.get(name)return hello, %s % (name)它直接返回前端输入的名字。那我们就可以构造如下url造成…

【Bug】Unable to make field private final int java.time.LocalDate.year accessible

问题描述 在使用这段代码时new Gson().toJson(result),会出现如下异常 Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final int java.time.LocalDate.year accessible: module java.base does not &q…

Ultra-Fast-Lane-Detection 车道线学习资料整理

目录 官方版本 两个优化 数据标注,降低参数量 1 数据标注 2降低参数量

华为李鹏:加速5G商业正循环,拥抱更繁荣的5.5G(5G-A)

2023年10月10日&#xff0c;在华为主办的第十四届全球移动宽带论坛上&#xff0c;华为高级副总裁、运营商BG总裁李鹏面向来自全球的运营商和产业伙伴&#xff0c;提出抓住网络需求和趋势的力量——“面向后天的业务&#xff0c;积极规划明天的网络&#xff0c;加速5G商业正循环…

Java数据结构第十七章、手撕位图

给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。【腾讯】 1. 遍历&#xff0c;时间复杂度O(N) 2. 排序(O(NlogN))&#xff0c;利用二分查找: logN 3. 位图解决 数据是否在给定的整形数据中&#xff0c;结…

uniapp快速入门系列(4)- 微信小程序开发

第四章 微信小程序开发 4.1 微信小程序开发与uniapp的融合4.2 微信小程序API在uniapp中的使用4.3 微信小程序常见问题的解决方法问题1: 如何获取用户信息&#xff1f;问题2: 如何获取当前位置&#xff1f;问题3: 如何发送网络请求&#xff1f; 在本章中&#xff0c;我们将学习如…

AUTOSAR汽车电子嵌入式编程精讲300篇-面向OTA的信息安全防护协议

目录 前言 国内外研究现状 汽车OTA相关技术以及常用加密算法介绍 2.1 引言

043:mapboxGL鼠标点击提示source属性信息

第043个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标点击提示source属性信息。这里用到了popup弹窗,用到了click事件,用到了鼠标样式的变化等功能。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源…

数据结构和算法(12):词典

词典 逻辑上的词典&#xff0c;是由一组数据构成的集合&#xff0c;其中各元素都是由关键码和数据项合成的词条&#xff08;entry&#xff09;。 映射&#xff08;map&#xff09;结构与词典结构一样&#xff0c;也是词条的集合。 二者的差别仅仅在于&#xff0c;映射要求不同…

无法打开文件“opengl32.lib”

无法打开文件“opengl32.lib” [TOC](无法打开文件“opengl32.lib”) 前言一、找到库链接配置勾选继承input里也要勾选继承 前言 随便找个教程配置结果报错无法打开文件opengl32.lib 分析原因&#xff1a; opengl库和windows自带库一样出问题应该是VS配置有问题 提示&#xff…
最新文章