新闻中心
C++如何实现生产者消费者模式_C++多线程同步与互斥经典案例
生产者消费者模式通过共享缓冲区、互斥锁和条件变量实现多线程同步,解决数据生产与消费速度不匹配问题,C++中利用queue、mutex和condition_variable完成线程间协调,确保线程安全与高效通信。

生产者消费者模式是多线程编程中的经典问题,用于解决生产数据与消费数据速度不匹配的问题。在C++中,通常使用互斥锁(std::mutex)、条件变量(std::condition_variable)和队列(std::queue)来实现线程间的同步与互斥。
核心组件说明
要实现生产者消费者模型,需要以下几个关键元素:
- 共享缓冲区:通常是一个队列,用于暂存生产者生成的数据,供消费者取出处理。
- 互斥锁(mutex):保护共享资源,防止多个线程同时访问导致数据竞争。
- 条件变量(condition_variable):用于线程间通信,当缓冲区为空时让消费者等待,当缓冲区有数据时通知消费者;当缓冲区满时让生产者等待,有空间时通知生产者。
代码实现示例
下面是一个基于固定大小缓冲区的生产者消费者模型实现:
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable not_empty;
std::condition_variable not_full;
const int max_buffer_size = 5;
void producer(int id) {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
not_full.wait(lock, []() { return buffer.size() < max_buffer_size; });
buffer.push(i);
std::cout << "生产者 " << id << " 生产: " << i << std::endl;
not_empty.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void consumer(int id) {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
not_empty.wait(lock, []() { return !buffer.empty(); });
int value = buffer.front();
buffer.pop();
std::cout << "消费者 " << id << " 消费: " << value << std::endl;
not_full.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
}
主函数中启动多个生产者和消费者线程:
Motiff妙多
Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”
334
查看详情
int main() {
std::thread p1(producer, 1);
std::thread p2(producer, 2);
std::thread c1(consumer, 1);
std::thread c2(consumer, 2);
p1.join();
p2.join();
c1.join();
c2.join();
return 0;
}
关键点解析
该实现中几个重要细节:
- 使用 std::unique_lock 配合条件变量,支持在等待时释放锁,并在被唤醒后重新获取。
- 条件变量的 wait 方法接受一个谓词(lambda表达式),避免虚假唤醒问题。
- 每次修改缓冲区后调用 notify_one() 唤醒一个等待线程,也可以使用 notify_all() 唤醒所有等待线程。
- 通过 std::this_thread::sleep_for 模拟生产/消费耗时,使输出更清晰。
应用场景与扩展
这种模式广泛应用于任务调度、消息队列、日志处理等场景。可以根据需求进行扩展:
- 使用循环队列或智能指针管理对象生命周期。
- 添加停止信号(如标志位)优雅关闭线程。
- 使用 std::shared_mutex 实现读写优化(若允许多个消费者同时读)。
- 封装成模板类,支持不同类型的数据。
基本上就这些。掌握这个模型对理解多线程同步机制非常有帮助。
以上就是C++如何实现生产者消费者模式_C++多线程同步与互斥经典案例的详细内容,更多请关注其它相关文章!
# 如何实现
# seo项目答辩考核
# 黑帽seo批量getshell
# 昌邑优化网站公司哪家好
# 2022免费推广网站
# 渭南绍兴网站推广
# 寄生虫seo广告
# 景观作图网站推广文案
# 可靠的seo平台广告
# 北海网站建设介绍服务
# 小吃店怎么做营销和推广
# 解决方法
# 怎么做
# 重写
# c++
# 几个
# 有什么
# 是一个
# 多个
# 互斥
# 多线程
# red
# 同步机制
# stream
# ios
# ai
# 生产者消费者模式
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
生成rdflib自定义SPARQL函数:参数匹配与实践指南
mysql备份恢复性能优化_mysql备份恢复性能优化方法
C++如何连接MySQL数据库_C++使用Connector/C++操作MySQL数据库教程
顺丰快件物流信息 官方网站查询入口
蛙漫限时开放最深处链接_蛙漫全站漫画会员同款秒开地址
mc.js游戏直达 mc.js网页免下载版本秒进地址
三星ZFold5多任务卡顿_Samsung ZFold5流畅度提升
打开就能玩的植物大战僵尸 植物大战僵尸网页版传送门
KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法
Win11怎么设置鼠标主按键_Win11鼠标左右键功能互换
创客贴用户入口官网登录 创客贴网页版电脑版系统
圆通快递查询实时追踪 圆通物流包裹状态快速查看
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
虫虫漫画精品漫画官网_虫虫漫画精品漫画官网进入精品漫画
PyTorch模型训练效果不佳?深入剖析常见错误与调试技巧
极兔快递快件信息查询系统 极兔快递官网运单号追踪
菜鸟取件码是什么怎么查 最全查询渠道汇总
C++指针和引用有什么区别_C++内存管理核心概念深度解析
顺丰快递查询系统 官方正版查询入口
React Router 嵌套组件中 URL 重定向问题的解决方案
QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口
J*aScript打印功能_j*ascript输出控制
限制HTML日期输入框的日期选择范围
Go语言中Map值调用指针接收器方法的限制与应对
俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问
Mac怎么锁定备忘录_Mac备忘录加密设置教程
从OpenAI API响应中高效提取生成文本
企业名称高精度匹配:N-gram方法在结构相似性分析中的应用
支付宝如何管理隐私设置_支付宝隐私保护的配置技巧
解决移动端滚动问题的overflow属性应用指南
邮政快递单号查询入口 邮政快递物流信息在线查询入口
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果
单12V-2×6实现为RTX 5090供电750W!甚至都没敢跑分
qq浏览器如何查看和导出已保存的密码 qq浏览器密码管理器数据备份教程
钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法
React Router v6 教程:构建认证保护的私有路由与重定向策略
Excel组合图表怎么做 Excel创建柱状图与折线组合图教程【图表】
Golang如何使用new_Go new分配内存机制讲解
千牛数据看板网页版_千牛数据看板网页版访问方法
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
HuggingFaceEmbeddings中向量嵌入维度调整的限制与理解
使用Pandas转换并合并DataFrame:多列映射至统一结构
纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析
在Go语言中利用后缀数组处理多字符串:实现高效文本匹配与自动补全
Golang指针如何与map组合使用_Golang map指针组合实践
Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】
MAC如何安全彻底地删除文件_MAC使用终端命令确保文件无法被恢复
精准捕获:如何在页面中监听除特定元素外的所有点击事件
QQ邮箱在线使用入口 QQ邮箱个人账号网页版登录


2025-11-26
浏览次数:次
返回列表
not_empty.wait(lock, []() { return !buffer.empty(); });
int value = buffer.front();
buffer.pop();
std::cout << "消费者 " << id << " 消费: " << value << std::endl;
not_full.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
}