[C++11 多线程同步] --- 条件变量的那些坑【条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)】

25 篇文章 ¥19.90 ¥99.00
本文探讨了C++11中条件变量在多线程同步中的两个关键问题:信号丢失和虚假唤醒。通过生产者消费者模型展示了信号丢失的场景,并提供了解决方案,即在wait前加入判断条件。接着,解释了虚假唤醒现象,提出通过while循环的附加条件判断来避免错误执行。最后,介绍了C++中condition_variable::wait的predicate方式,简化了处理虚假唤醒的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 条件变量的信号丢失

1.1 条件变量的信号丢失场景重现

拿生产者和消费者模型举例,看一段示例代码:

#include <iostream>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <unistd.h>

std::mutex mutex;
std::condition_variable cv;
std::vector<int> vec;

void consumer() 
{
	sleep(1);
    std::unique_lock<std::mutex> lock(mutex);
    std::cout << "blocking on wait" << std::endl;
    cv.wait(lock);
    std::cout << "executed wait" << std::endl;
    std::cout << "consume " << vec.size() << "\n";
}

void produce() {
    std::unique_lock<std::mutex> lock(mutex);
    vec.push_back(1);
    cv.notify_all();
    st
<think>嗯,用户之前问过关于C++的shared_mutex,现在又在问条件变量是什么时候引入C++的。首先,我需要确认用户的问题是关于条件变量C++标准中的哪个版本被引入的。用户可能是在学习多线程编程,或者在项目中遇到了同步问题,需要了解同版本C++的支持情况。 接下来,我应该回忆一下C++标准的历史。C++11是一个重要的版本,引入了很多多线程相关的库,比如std::thread、mutex等。而条件变量作为多线程同步的重要工具,很可能也是在C++11中加入的。过要确认这一点,可能需要查阅相关资料或标准文档。 另外,用户之前的问题是关于shared_mutex,属于C++17的内容,而这次的问题可能涉及到更早的版本。这时候需要指出条件变量是在C++11引入的,而shared_mutex是在C++17引入的,避免混淆。 然后,用户的提问方式可能表明他们正在学习多线程编程,对同的同步机制感兴趣。因此,除了回答版本信息外,可能需要简要说明条件变量的基本用法与互斥量的配合使用,这样用户能得到更全面的信息。 另外,要注意用户可能的实际需求,比如他们可能在移植旧代码到新标准,或者需要确保代码在同编译器下的兼容性。这时候可能需要提到在C++11之前,可能需要使用Boost库或其他实现,而C++11之后的标准库提供了原生支持。 还要考虑用户可能的后续问题,例如条件变量的具体用法,或者与其它同步机制的区别,所以在回答中可以适当给出示例代码或使用场景,但当前问题主要是版本引入,所以需要太深入,但简要提及可以增加回答的实用性。 最后,确保回答准确,避免错误,比如确认C++11确实引入了std::condition_variablestd::condition_variable_any,并且说明它们的区别,这样用户能更清楚选择哪个更适合他们的场景。</think>C++ 中的 **条件变量(`std::condition_variable`)** 是 C++11 标准引入的同步机制,用于在多线程编程中实现线程间的**等待与唤醒**机制。它与互斥量(`std::mutex`)配合使用,能够高效地实现线程的阻塞条件触发,避免忙等待(busy-waiting)。 --- ### **关键点** 1. **引入版本** - **C++11** 首次在标准库中引入条件变量,包含以下两个类: - `std::condition_variable`(默认实现,通常性能更高) - `std::condition_variable_any`(更通用,可与任何满足“锁”概念的类型配合使用) 2. **核心功能** - 允许线程在某个条件满足时主动阻塞,直到其他线程修改条件并通知(notify)它恢复运行。 - 典型场景:生产者-消费者模型、任务队列调度等。 --- ### **基本用法** ```cpp #include <iostream> #include <thread> #include <mutex> #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false; // 等待线程 void wait_thread() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [] { return ready; }); // 等待条件满足(ready == true) std::cout << "条件满足,继续执行!" << std::endl; } // 通知线程 void notify_thread() { std::this_thread::sleep_for(std::chrono::seconds(2)); { std::lock_guard<std::mutex> lock(mtx); ready = true; } cv.notify_one(); // 唤醒一个等待线程 } int main() { std::thread t1(wait_thread); std::thread t2(notify_thread); t1.join(); t2.join(); return 0; } ``` --- ### **核心方法** - **等待(阻塞当前线程)** - `wait(lock, predicate)`:自动释放锁并阻塞,直到被唤醒且 `predicate` 返回 `true`。 - `wait_for()` / `wait_until()`:支持超时等待。 - **唤醒其他线程** - `notify_one()`:唤醒一个等待线程。 - `notify_all()`:唤醒所有等待线程。 --- ### **注意事项** 1. **必须与互斥量配合使用** 条件变量的操作需在互斥量的保护下进行,以确保条件检查的原子性。 2. **虚假唤醒Spurious Wakeup)** 条件变量的 `wait` 可能因系统原因意外唤醒,因此必须通过**循环检查条件**或直接在 `wait` 中传入断言(predicate)。 3. **性能优化** - 优先使用 `std::condition_variable`,而非 `std::condition_variable_any`(后者更灵活但开销更大)。 - 避免频繁唤醒,合理选择 `notify_one()` 或 `notify_all()`。 --- ### **C++11 前的替代方案** 在 C++11 之前,开发者通常依赖平台特定的 API(如 POSIX 的 `pthread_cond_t`)或第三方库(如 Boost 的 `boost::condition_variable`)。 --- 条件变量C++ 多线程编程的核心工具之一,合理使用可以显著提升程序的并发效率资源利用率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Overboom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值