新闻中心

C++ condition_variable教程_C++生产者消费者模型实现详解

2025-11-29
浏览次数:
返回列表
condition_variable用于C++多线程同步,配合mutex实现生产者-消费者模型:生产者在缓冲区满时等待,消费者在空时等待,通过wait+谓词避免虚假唤醒,notify_all通知对应线程,确保安全高效协作。

c++ condition_variable教程_c++生产者消费者模型实现详解

在C++多线程编程中,condition_variable 是实现线程间同步的重要工具之一。它常用于解决生产者-消费者这类协作问题,确保多个线程在共享资源访问时能够安全、高效地协同工作。

condition_variable 基本概念

condition_variable 定义在 头文件中,必须与 std::mutex 配合使用。它的核心作用是让线程在某个条件不满足时进入等待状态,直到其他线程修改了共享状态并通知它。

关键成员函数包括:

  • wait(lock, predicate):释放锁并阻塞线程,直到被唤醒且谓词为真
  • notify_one():唤醒一个等待的线程
  • notify_all():唤醒所有等待的线程

使用 wait 时推荐传入谓词(lambda 或函数对象),避免虚假唤醒带来的问题。

生产者-消费者模型设计思路

该模型包含两类线程:

  • 生产者:向共享缓冲区添加数据
  • 消费者:从缓冲区取出数据处理

需要解决的问题:

  • 缓冲区满时,生产者应等待
  • 缓冲区空时,消费者应等待
  • 对缓冲区的访问必须互斥

为此引入:

N世界 N世界

一分钟搭建会展元宇宙

N世界 138 查看详情 N世界
  • 一个互斥量(mutex)保护缓冲区
  • 一个 condition_variable 供生产者等待
  • 另一个 condition_variable 供消费者等待

代码实现示例

以下是一个完整的 C++ 实现:

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>

std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cv_full; // 缓冲区未满
std::condition_variable cv_empty; // 缓冲区非空

const int max_size = 5;

void producer(int id) {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        cv_full.wait(lock, []{ return buffer.size() < max_size; });
        
        buffer.push(i);
        std::cout << "生产者 " << id << " 生产: " << i << "\n";
        
        lock.unlock();
        cv_empty.notify_all(); // 通知消费者可以消费
        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);
        cv_empty.wait(lock, []{ return !buffer.empty(); });
        
        int value = buffer.front();
        buffer.pop();
        std::cout << "消费者 " << id << " 消费: " << value << "\n";
        
        lock.unlock();
        cv_full.notify_all(); // 通知生产者可以生产
        std::this_thread::sleep_for(std::chrono::milliseconds(150));
    }
}

main 函数启动多个生产者和消费者:

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

注意事项与最佳实践

使用 condition_variable 时需注意:

  • 始终使用 unique_lock 而不是 lock_guard,因为 wait 会原子性地释放锁
  • wait 的谓词判断必不可少,防止虚假唤醒导致逻辑错误
  • notify 后不必立即释放锁,但应尽快减少临界区范围
  • 考虑使用 notify_one() 减少不必要的线程唤醒开销,除非确实需要唤醒全部等待者

在实际项目中,可将缓冲区封装成一个线程安全的类,隐藏同步细节,提高代码复用性。

基本上就这些。掌握 condition_variable 的正确用法,是写出健壮多线程程序的关键一步。

以上就是C++ condition_variable教程_C++生产者消费者模型实现详解的详细内容,更多请关注其它相关文章!


# 是一个  # 都江堰网站推广选哪家  # 泉州seo优化指南  # Wp中文seo插件  # 东莞优化网站单价  # 兄弟素材网站建设需要  # 苹果生鲜营销推广文案范文  # 长沙网站建设课程总结  # 太原网站建设市场分析  # 营销策划与推广照片  # 利通区大数据全网营销推广怎么做  # 相关文章  # 互斥  # 编解码  # 工具  # 有什么区别  # 如何使用  # 复用  # 多个  # 如何实现  # 多线程  # red  # 代码复用  # stream  # ios  # c++  # ai 


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


相关推荐: J*aScript map 迭代中检测空数组元素的有效方法  邮政编码查询不到怎么办_邮政编码查询不到的常见原因与对策  小米汽车11月交付量突破40000台!雷军:将继续努力  Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性  在python-socketio事件处理器中安全访问Flask应用上下文  网易大神怎么保存别人动态的图片_网易大神动态图片保存方法  如何优雅地解决Livewire文件上传难题?SpatieLivewireFilepond让一切变得简单  解决Django多数据库/多Schema环境下外键迁移问题  Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】  大象笔记网页版入口 印象笔记网页版登录入口  《噬血代码2》新预告片发布 展示游戏剧情  深入理解与实现最大堆的Heapify过程:常见错误与修正  如何创建没有密码的Windows本地账户_跳过微软账户登录的技巧【教程】  12306几点到几点不能订票? | 官方最新系统维护时间全解析  《主播少女的秘密账号迷宫》首支宣传片  一加Ace 6T支持全新明眸护眼:通过了最严苛的护眼小金标认证  如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!  Tabulator表格中精确实现日期时间排序的指南  Go语言中对Map值调用带指针接收者方法:原理与最佳实践  sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置  新手怎么开始学化妆 零基础化妆入门教程  vivo手机参数配置怎么增强信号_vivo手机参数配置信号增强方法  一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰  Pandas DataFrame:高效添加条件计算列  漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口  Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法  汽车之家官方网站官网入口_汽车之家网页版直接进入  VS Code远程开发时如何处理文件权限问题  sublime怎么预览Markdown渲染效果_Markdown Preview插件 for sublime教程  c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  魅族20怎样在浏览器开无图省流_iPhone魅族20浏览器开无图省流【流量节省】  zookeeper 都有哪些功能?  CSS如何设置hover状态颜色_hover伪类调整背景或文字颜色  如何仅使用CSS更改登录界面背景图像图标的颜色  必由学官方网站入口 必由学学生教师共用登录通道  Kafka Streams中基于消息头条件过滤消息的实现指南  优化Log4j2控制台输出性能:解决异步日志瓶颈  CSS自定义字体样式被系统字体替换怎么办_font-face方式指定font-display控制渲染策略  J*aScript类型检查_j*ascript代码规范  蛙漫限时开放最深处链接_蛙漫全站漫画会员同款秒开地址  j*a toString()的覆盖  微信语音通话掉线如何解决 微信语音通话稳定优化方法  Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题  树莓派传感器触发:通过Twilio API发送WhatsApp消息教程  sublime如何配置Go语言开发环境_sublime搭建Golang编译运行系统  “音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!  机器学习中对数变换预测结果的反向还原  12306选座怎么选到商务座_12306商务座选择与配置说明  AO3官方可用镜像 Archive of Our Own网页版最新入口 

搜索