新闻中心

C++怎么实现生产者消费者模型_C++多线程并发模型与生产者消费者实现

2025-12-06
浏览次数:
返回列表
生产者消费者模型通过互斥锁和条件变量实现线程安全的缓冲区共享,生产者在缓冲区未满时添加数据,消费者在非空时取出数据,配合谓词等待避免虚假唤醒,使用notify_one提升效率,可通过结束标志正常退出线程。

c++怎么实现生产者消费者模型_c++多线程并发模型与生产者消费者实现

生产者消费者模型是多线程编程中的经典问题,用于描述多个线程之间如何安全地共享有限缓冲区的数据。C++中可以通过标准库的多线程支持(<thread></thread><mutex></mutex><condition_variable></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_full;
std::condition_variable not_empty;

const int max_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_size; });
        buffer.push(i);
        std::cout << "Producer " << id << " produced: " << i << "\n";
        lock.unlock();
        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 << "Consumer " << id << " consumed: " << value << "\n";
        lock.unlock();
        not_full.notify_one();
        std::this_thread::sleep_for(std::chrono::milliseconds(150));
    }
}

在主函数中启动多个生产者和消费者线程即可观察协同工作:

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;
}

关键机制说明

条件变量等待必须配合谓词使用:避免虚假唤醒导致逻辑错误。例如 not_full.wait(lock, [](){ return buffer.size() 确保只有真正满足条件时才继续执行。

简小派 简小派

简小派是一款AI原生求职工具,通过简历优化、岗位匹配、项目生成、模拟面试与智能投递,全链路提升求职成功率,帮助普通人更快拿到更好的 offer。

简小派 123 查看详情 简小派

notify_one 与 notify_all 的选择:若只有一个等待线程需被唤醒,用 notify_one 更高效;若存在多个同类等待者,根据场景决定是否广播。

解锁后通知:先释放锁再调用 notify 可减少唤醒后立即阻塞的概率,提升性能。

可改进方向

  • 使用智能指针或自定义消息结构传递复杂数据
  • 引入结束标志位,使消费者在生产完成后续正常退出
  • 采用循环缓冲区或双缓冲技术提升吞吐量
  • 使用 std::atomic 标记运行状态,避免强制终止线程

加入结束控制的简单方式是在共享区域添加:

bool done = false;
// 消费者中检测
not_empty.wait(lock, []() { return !buffer.empty() || done; });
if (done && buffer.empty()) break;
基本上就这些。C++11以后的标准库已足够支撑健壮的生产者消费者模型,关键是正确使用锁和条件变量组合,确保线程安全与响应性。

以上就是C++怎么实现生产者消费者模型_C++多线程并发模型与生产者消费者实现的详细内容,更多请关注其它相关文章!


# 边缘  # 淘宝客精品推广网站  # 网站运营海外营销推广  # 开封城市推广官方网站下载  # 云南网站优化简历软件  # 传智播客网站建设  # 桂林提升seo推广招聘  # seo满分模板  # 怎么进入谷歌seo  # 阿里云网站建设合同  # 品牌企业展示网站建设  # 相关文章  # 是在  # ai  # 是一个  # 未满  # 尼克  # 互斥  # 游戏开发  # 多个  # 多线程  # 标准库  # 数据访问  # stream  # ios  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Fabric Mod开发:在1.19.3+版本中正确添加自定义物品并管理物品组  excel如何生成目录 excel一键生成工作表目录超链接  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  CSS响应式网页如何实现主次模块比例自适应_flex-grow与flex-shrink调整  C++ typeid如何获取类型信息_C++ RTTI运行时类型识别用法  LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理  qq音乐在线播放入口_qq音乐电脑版登录链接  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  在J*a项目里如何构建对象之间的契约_接口约束的实际落地  微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法  谷歌浏览器一键优化方案_谷歌浏览器直达主页极速不卡版  c++如何使用折叠表达式(Fold Expressions)_c++17可变参数模板新技巧  在Runstone环境中高效处理TasteDive API的JSON数据  必由学在线入口 必由学网页版快速登录入口  一加 14R 快充无反应_一加 14R 充电优化  没有大陆身份证/银行卡如何实名微信? 亲测有效的几种方法分享  打开就能玩的植物大战僵尸 植物大战僵尸网页版传送门  J*aScript实现单选按钮与关联输入框的联动禁用教程  包子漫画官方网站在线链接-包子漫画在线阅读平台主页地址  windows10怎么查看硬盘序列号_windows10硬盘id查询命令  2025年云电脑操作系统体验 | 无需本地硬件,随时随地使用高性能PC  漫蛙网页登录入口 漫蛙漫画官方授权网址  Excel文件在线转换快速入口 Excel在线格式转换网站  Win11怎么设置鼠标主按键_Win11鼠标左右键功能互换  魅族17怎样用浏览器译外语网页_iPhone魅族17浏览器译外语网页【即时翻译】  CSS Grid如何控制元素对齐_align-items与justify-items组合使用  一加 Nord 5 隐私权限异常_一加 Nord 5 系统安全优化  QQ邮箱在线登录平台 QQ邮箱个人邮箱网页版入口  Yandex免登录网页版地址 Yandex搜索引擎官方访问入口  可靠CSGO开箱平台解析 CSGO开箱网合集  HTML长属性值处理:表单action路径优化与代码规范应对  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  印象笔记如何设提醒任务防漏执行_印象笔记设提醒任务防漏执行【任务提醒】  Basecamp怎样用留言钉固定重点_Basecamp用留言钉固定重点【重点标记】  小米汽车11月交付量突破40000台!雷军:将继续努力  腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程  J*aScript中正确使用querySelectorAll与复杂CSS选择器  Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐  小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口  J*aScript map 方法中处理循环元素为空数组的策略  漫蛙漫画登录站点 漫蛙2正版漫画快速访问  葱吃多了会怎样 葱吃多了会伤胃吗  outlook中文官网入口地址 outlook官方中文版直达首页链接  Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践  淘宝网网页版登录入口 淘宝官方网页版快捷登录  哔哩哔哩忘记密码了怎么找回_哔哩哔哩密码找回方法  夸克AO3官网入口_AO3镜像网站2025推荐  铁路12306的积分有效期是多久_铁路12306积分有效期说明  Excel如何用迷你图显趋势_Excel用迷你图显趋势【趋势小图】  Lar*el 递归关系中排除指定分支的教程 

搜索