新闻中心

c++ 怎么使用条件变量std::condition_variable_c++线程等待与条件同步实现

2025-11-15
浏览次数:
返回列表
std::condition_variable用于线程同步,需与std::mutex配合使用,通过wait()等待条件,notify_one()/notify_all()通知;必须在锁保护下等待,推荐带谓词的wait防止虚假唤醒,通知前应先修改共享数据并释放锁。

c++ 怎么使用条件变量std::condition_variable_c++线程等待与条件同步实现

在C++多线程编程中,std::condition_variable 是实现线程间条件同步的重要工具。它通常与 std::mutex 配合使用,用于让一个或多个线程等待某个特定条件成立后再继续执行。

条件变量的基本原理

条件变量本身不存储状态,它只是一个通知机制。线程可以:

  • 等待某个条件成立(调用 wait())
  • 当条件可能变化时,由其他线程发出通知(notify_one() 或 notify_all())

关键点是:等待必须在互斥锁保护下进行,且通常使用循环检查条件,防止虚假唤醒。

基本使用步骤

以下是使用 std::condition_variable 的标准模式:

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

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker_thread() {
    std::unique_lock<std::mutex> lock(mtx);
    // 等待直到 ready 为 true
    cv.wait(lock, []{ return ready; });
    std::cout << "工作线程开始执行任务\n";
}

int main() {
    std::thread worker(worker_thread);

    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();  // 唤醒一个等待的线程

    worker.join();
    return 0;
}

wait 的两种形式

cv.wait(lock):无条件等待,醒来后需手动检查条件。

Reachout.ai Reachout.ai

一个AI驱动的视频开发平台,专为忙碌的企业家和销售团队打造

Reachout.ai 142 查看详情 Reachout.ai

cv.wait(lock, predicate):带条件的等待,等价于:

while (!predicate()) {
    wait(lock);
}

推荐使用带谓词的版本,能自动处理虚假唤醒。

通知方式的选择

  • notify_one():唤醒一个等待线程,适用于只有一个消费者的情况
  • notify_all():唤醒所有等待线程,适用于多个消费者或广播场景

注意:通知前应先修改共享数据并释放锁,否则被唤醒的线程可能无法立即获取锁。

生产者-消费者模型示例

常见应用场景:用条件变量实现线程安全的任务队列。

#include <queue>
#include <thread>
#include <condition_variable>

std::queue<int> tasks;
std::mutex task_mutex;
std::condition_variable task_cv;
bool finished = false;

void producer() {
    for (int i = 0; i < 5; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::lock_guard<std::mutex> lock(task_mutex);
        tasks.push(i);
        std::cout << "生产任务: " << i << "\n";
        task_cv.notify_one();
    }
    {
        std::lock_guard<std::mutex> lock(task_mutex);
        finished = true;
    }
    task_cv.notify_all();  // 通知消费者结束
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(task_mutex);
        task_cv.wait(lock, []{ return !tasks.empty() || finished; });

        if (finished && tasks.empty()) break;

        int task = tasks.front();
        tasks.pop();
        lock.unlock();  // 处理任务时不持有锁
        std::cout << "消费任务: " << task << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
}
基本上就这些。核心是:用互斥锁保护共享状态,用条件变量等待特定条件,记得处理虚假唤醒和正确发送通知。

以上就是c++++ 怎么使用条件变量std::condition_variable_c++线程等待与条件同步实现的详细内容,更多请关注其它相关文章!


# ai  # 好的网站seo优化软件  # 温州建设质监网站登录  # 药店网站建设价格  # 亦庄企业网站建设推广  # 河南营销全网推广平台  # 东北排名优化seo公司  # 品牌营销推广哪家正规  # 红酒营销推广方案范本  # 湘潭营销推广平台官网首页  # 两种  # 互斥  # 内存管理  # 是一个  # 应先  # 如何实现  # 适用于  # 多个  # 多线程  # 如何使用  # 有锁  # red  # stream  # ios  # c++  # 工具  # 婚恋关键词排名推荐 


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


相关推荐: 在Runstone环境中高效处理TasteDive API的JSON数据  漫蛙漫画官方首页 漫蛙2漫画在线阅读入口  Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】  新手怎么开始学化妆 零基础化妆入门教程  React/Next.js中实现列表项的动态选择与移动  CSS图片焦点样式实现教程:理解与应用tabindex属性  Lar*el递归关系中排除子孙节点的策略  快手极速版在线观看 官方网页版登录地址  实现分段式页面滚动导航:CSS与J*aScript教程  Lar*el 递归关系中排除指定分支的教程  qq游戏大厅官方下载_qq游戏免费下载安装入口  C++20的source_location是什么_C++在编译期获取源码位置信息用于日志和断言  J*aScript中如何高效提取对象指定属性  word中如何让数字纵向排列_Word数字纵向排列方法  外媒分析《GTA6》定价:卖100美元可以但真没必要!  随机参数递归函数的基准调用次数与时间复杂度探究  在FastAPI中利用lifespan与依赖注入高效管理Redis连接池  b站怎么取消点赞_b站点赞取消操作方法  fishbowl官网免费版 fishbowl养鱼网站入口  Golang如何测试channel通信行为_Golang channel通信测试与分析方法  Tailwind CSS line-clamp 布局问题解析与修复指南  动漫花园资源网使用步骤_动漫花园资源网下载流程  Tabulator表格中精确实现日期时间排序的指南  ArrayList与LinkedList操作复杂度详解:遍历与修改  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  Archive of Our Own官网直达 AO3最新可用地址一览  Angular Material 垂直步进器:实现底部到顶部排序的教程  vivo手机互传视频怎么操作_vivo手机互传视频详细传输方法  网易大神账号申诉需要多久_网易大神账号申诉流程说明  自定义Bag-of-Words实现:处理带负号的词汇权重  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  Lar*el 8 多关键词数据库搜索优化实践  J*aScript类型检查_j*ascript代码规范  荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】  J*a里如何使用forEach遍历Map_Map遍历方法说明  Flexbox布局实践:实现粘性导航栏与底部固定页脚  Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录  处理Kafka消费者会话超时:深入理解消息处理语义与幂等性  J*a应用集成GitHub CLI与API认证指南  QQ邮箱稳定登录入口_QQ邮箱官方网站网页版使用  Win11输入法不见了怎么办_Windows11恢复语言栏显示方法  Python多版本共存与虚拟环境管理深度指南  Win11怎么开启高性能模式_Windows 11电源计划优化设置  如何将HTML表格多行数据保存到Google Sheet  漫蛙2在线漫画入口 漫蛙正版漫画网页版直达  Sublime Text怎么显示空格和制表符_Sublime显示不可见字符设置  解决 Vaadin 8 中大文件音频播放与定位时出现的 IOException  c++ 获取系统当前时间 c++时间戳获取方法  Windows10怎么开启夜间模式 Windows10系统设置调整色温与亮度缓解夜间用眼疲劳【教程】  天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南 

搜索