信息发布→ 登录 注册 退出

c++怎么使用条件变量std::condition_variable_c++多线程条件变量用法

发布时间:2025-11-05

点击量:
std::condition_variable需与std::unique_lock配合使用,通过wait()等待条件并释放锁,由notify_one()或notify_all()唤醒线程,常用于生产者-消费者模型,需用谓词避免虚假唤醒,确保线程安全同步。

c++怎么使用条件变量std::condition_variable_c++多线程条件变量用法

在C++多线程编程中,std::condition_variable 是一个重要的同步机制,用于在线程之间协调“等待-通知”操作。它通常与 std::unique_lock<:mutex> 配合使用,让某个线程等待特定条件成立,而另一个线程在条件达成时发出通知。

基本用法:等待与唤醒

std::condition_variable 的核心是两个方法:wait()notify_one()notify_all()

典型使用场景包括生产者-消费者模型、任务队列等。下面是一个简单的例子:

刺鸟创客 刺鸟创客

一款专业高效稳定的AI内容创作平台

刺鸟创客 110 查看详情 刺鸟创客
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

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

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

int main() {
    std::thread t1(worker_thread);
    std::thread t2(main_thread);

    t1.join();
    t2.join();
    return 0;
}

关键点说明

  • 必须配合互斥锁使用:condition_variable 的 wait 操作需要传入 unique_lock,不能单独使用。
  • wait 会自动释放锁:调用 wait 时,线程释放锁并进入阻塞状态;被唤醒后重新获取锁再继续执行。
  • 使用 lambda 判断条件:推荐在 wait 第二个参数传入谓词(如 []{return ready;}),避免虚假唤醒导致的问题。
  • notify_one vs notify_all:notify_one() 唤醒一个等待线程,notify_all() 唤醒所有等待线程,根据场景选择。

生产者-消费者示例

更实用的例子:多个线程处理任务队列。

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

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

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(task_mutex);
        // 等待任务或结束信号
        task_cv.wait(lock, []{ return !tasks.empty() || finished; });

        if (finished && tasks.empty()) {
            lock.unlock();
            break;
        }

        int task = tasks.front();
        tasks.pop();
        lock.unlock();

        std::cout << "处理任务: " << task << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void producer() {
    for (int i = 1; i <= 5; ++i) {
        {
            std::lock_guard<std::mutex> lock(task_mutex);
            tasks.push(i);
        }
        task_cv.notify_one();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    {
        std::lock_guard<std::mutex> lock(task_mutex);
        finished = true;
    }
    task_cv.notify_all(); // 唤醒所有消费者结束
}

int main() {
    std::thread c(consumer);
    std::thread p(producer);

    p.join();
    c.join();
    return 0;
}

基本上就这些。掌握 condition_variable 的关键是理解它和互斥锁的协作方式,以及如何安全地传递状态变化。只要注意加锁、使用谓词等待、及时通知,就能写出可靠的多线程代码。

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


相关文章: 《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!  品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程  微信网页版登录教程_微信网页版登录入口在哪  浏览器打开即用 美图秀秀网页版入口  俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口  小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】  苹果手机指南针不准怎么校准 传感器校准方法详解【建议收藏】  126邮箱手机版登录官网2026_126手机邮箱免费入口最新  QQ邮箱网页版入口 QQ邮箱官方邮箱登录通道  大象笔记网页版入口 印象笔记网页版登录入口  c++如何使用std::memory_order控制原子操作顺序_c++ C++11内存模型详解  如何在J*a中使用Locale处理多语言环境  PySpark中从现有列右侧提取可变长度字符创建新列的教程  uc浏览器网页版入口 uc浏览器网页版最新网址  包子漫画官方网站阅读入口-包子漫画在线漫画官网直达链接  Vue.js 图片显示异常排查:理解应用挂载范围与DOM ID唯一性  2025俄罗斯Yandex最新入口 官方网站地址及浏览器下载指南  J*aScript数组对象转换:按指定键分组与值收集  优化Lar*el Docker镜像:Composer与PHP版本控制策略  win11专注助手在哪 Win11免打扰模式设置与自动化规则【指南】  葱吃多了会怎样 葱吃多了会伤胃吗  必由学官网首页入口 必由学教师网页版登录指南  必由学官网快捷入口 必由学网页版在线学习平台  如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置  Mac怎么查看崩溃日志_Mac控制台错误报告分析  使用PHP DOM解析器高效提取HTML中特定标题及其紧邻段落  C++如何打印当前代码行号与文件名_C++预定义宏FILE与LINE的使用  html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】  QQ邮箱登录平台入口 QQ邮箱网页版邮箱官方入口  谷歌邮箱注册显示错误Gmail服务器异常与延迟处理  如何提高微信支付的安全性_微信支付安全防护与设置建议  PHP实现即时文章发布与单次数据库写入:自提交模式教程  AO3同人作品网入口 AO3搜索引擎官网永久地址  在J*a中如何使用Stream.map转换元素_Stream映射操作解析  AO3官方镜像站点汇总 AO3同人作品网页版直达链接  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  海棠账号登录入口_登录海棠账户同步阅读记录  外媒分析《GTA6》定价:卖100美元可以但真没必要!  sublime怎么格式化代码_sublime代码美化与一键排版插件配置  内存检查:在VS Code中调试C++时的内存视图  如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!  PHP表单提交后函数重复执行的解决方案:管理$_POST数据  Python异步编程实践:使用Binance API构建实时交易数据流  Go语言中Map存储的结构体如何调用指针方法:深入解析与实践  将JSON对象数组转置为键值对列表的实用指南  mcjs网页版流畅运行 mcjs低配电脑畅玩入口  mysql如何分析事务日志_mysql事务日志分析方法  文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】  Golang如何通过reflect获取匿名字段方法_Golang reflect匿名字段方法访问技巧  vivo手机参数配置怎么增强信号_vivo手机参数配置信号增强方法 

在线客服
服务热线

服务热线

4008988990

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!