C++中std::condition_variable 条件变量的使用

 更新时间:2025年07月10日 09:39:17   作者:Ring__Rain  
std::condition_variable是C++多线程编程中用于线程间同步的核心工具,适用于需要协调多个线程行为、避免资源浪费的场景,下面就来介绍一下std::condition_variable 条件变量的使用,

作用:std::condition_variable 是 C++ 多线程编程中用于线程间同步的核心工具,其使用场景和核心价值体现在以下几个方面:        

一、何时使用 std::condition_variable?

  • 线程需要等待特定条件成立当某个线程必须等待共享资源的某个状态(如队列非空、任务完成、数据就绪等)时,使用条件变量可以避免忙等待(busy-waiting),从而减少 CPU 资源的浪费。

    经典场景
    • 生产者-消费者模型:消费者线程等待队列中有数据时,生产者线程在添加数据后通过 notify_one() 或 notify_all() 通知消费者。
    • 任务调度:工作线程等待任务队列中出现新任务。
  • 需要多线程协作完成复杂逻辑当多个线程需要按特定顺序协作时(如线程 A 完成预处理后通知线程 B 执行),条件变量提供了一种高效的协调机制。

    示例:主线程等待所有子线程初始化完成后再启动核心逻辑。
  • 避免轮询和资源浪费若用 while (条件不满足) { sleep(); } 实现等待,会导致线程频繁切换上下文和无效轮询,而条件变量通过阻塞线程直接释放 CPU,直到被主动唤醒。

  • 需要动态调整线程行为例如,线程池中的工作线程根据任务负载动态休眠或唤醒。

​二、为什么使用 std::condition_variable?

  • ​解决线程同步中的“等待-通知”问题条件变量通过 wait() 和 notify_*() 的组合,实现线程间的精准通知机制:

    • wait():释放互斥锁并阻塞线程,允许其他线程操作共享资源。
    • ​notify_one()/notify_all():唤醒一个或所有等待线程,确保资源状态变化后及时响应。
  • ​避免虚假唤醒(Spurious Wakeup)​操作系统的底层实现可能导致线程被意外唤醒(即使未收到通知)。条件变量通过 ​谓词(Predicate)​ 参数(如 cv.wait(lock, []{ return ready; }))确保只有在条件真正满足时才继续执行。

  • ​优化锁的粒度条件变量与 std::mutex 配合使用时,允许在等待期间释放锁,其他线程可继续操作共享资源,避免长时间锁竞争。

  • ​替代低效的轮询机制相比轮询(如 sleep() + 循环检查),条件变量通过操作系统级的线程调度实现高效阻塞,减少 CPU 占用。

​三、使用示例与核心步骤

​基本流程

定义共享变量和同步工具

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

等待线程

std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return data_ready; });  // 阻塞直到 data_ready 为 true

通知线程

{
    std::lock_guard<std::mutex> lock(mtx);
    data_ready = true;
}
cv.notify_one();  // 唤醒一个等待线程

​经典案例:生产者-消费者模型

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

std::mutex mtx;
std::condition_variable cv;
std::queue<int> task_queue;

void producer() {
    for (int i = 0; i < 10; ++i) {
        {
            std::lock_guard<std::mutex> lock(mtx);
            task_queue.push(i);
        }
        cv.notify_one();  // 通知消费者
    }
}

void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !task_queue.empty(); });  // 等待队列非空
        int task = task_queue.front();
        task_queue.pop();
        lock.unlock();
        // 处理任务
    }
}

​四、注意事项

  • 必须与互斥锁配合使用
    所有对共享变量的修改和访问必须通过互斥锁保护,否则会导致竞态条件(Race Condition)。

  • 正确处理虚假唤醒
    始终使用带谓词的 wait() 形式(如 cv.wait(lock, predicate))。

  • 避免“唤醒丢失”​
    确保在修改共享状态后调用 notify_*(),否则等待线程可能永远阻塞。

​总结

std::condition_variable 的核心价值在于通过 ​等待-通知机制 实现高效的线程同步,适用于需要协调多个线程行为、避免资源浪费的场景。其设计解决了传统轮询的低效问题,并通过与互斥锁的配合优化了多线程程序的性能与安全性。

到此这篇关于C++中std::condition_variable 条件变量的使用的文章就介绍到这了,更多相关C++ std::condition_variable 条件变量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++数据结构与算法之反转链表的方法详解

    C++数据结构与算法之反转链表的方法详解

    这篇文章主要介绍了C++数据结构与算法之反转链表的方法,结合实例形式分析了C++反转链表的原理、实现方法及相关注意事项,需要的朋友可以参考下
    2017-08-08
  • C++中继承基类与派生类的区别

    C++中继承基类与派生类的区别

    这篇文章主要介绍了C++中继承基类与派生类的区别,面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易,需要的朋友可以参考下
    2023-05-05
  • C语言循环控制入门介绍

    C语言循环控制入门介绍

    大家好,本篇文章主要讲的是C语言循环控制入门介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 纯C语言实现火车售票系统

    纯C语言实现火车售票系统

    这篇文章主要为大家详细介绍了纯C语言实现火车售票系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C++ Virtual关键字的具体使用

    C++ Virtual关键字的具体使用

    这篇文章主要介绍了C++ Virtual关键字的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • vc中float与DWORD的互想转换实现代码

    vc中float与DWORD的互想转换实现代码

    这篇文章主要介绍了vc中float与DWORD的互想转换实现代码,需要的朋友可以参考下
    2017-06-06
  • C语言银行系统课程设计

    C语言银行系统课程设计

    这篇文章主要为大家详细介绍了C语言银行系统课程设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • C语言读写配置文件的方法

    C语言读写配置文件的方法

    这篇文章主要介绍了C语言读写配置文件的方法,包括C语言读写ini配置文件所涉及的文件读写技巧,以及完整的源文件及头文件实现方法,需要的朋友可以参考下
    2015-07-07
  • C++如何解决rand()函数生成的随机数每次都一样的问题

    C++如何解决rand()函数生成的随机数每次都一样的问题

    这篇文章主要介绍了C++如何解决rand()函数生成的随机数每次都一样的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • ipv6实现tcp编程示例

    ipv6实现tcp编程示例

    这篇文章主要介绍了ipv6实现tcp编程示例,需要的朋友可以参考下
    2014-03-03

最新评论