【C++】std::condition_variable

C++ condition_variable 学习笔记

基本概念

std::condition_variable 是 C++ 标准库中用于多线程同步的重要工具之一。它可以与 std::mutex 一起使用,实现线程之间的等待和唤醒机制。通过 std::condition_variable,一个线程可以等待另一个线程满足某个特定条件,而不需要使用轮询等待的方式,这样有助于节省 CPU 资源,提高程序的性能。

内部原理

std::condition_variable 的内部原理通常是基于操作系统提供的条件变量或信号量实现的。在大多数情况下,它使用了操作系统底层的原子操作和同步机制,以确保线程的安全等待和唤醒。具体的实现细节可能会因操作系统和编译器而异。

成员函数

std::condition_variable 类提供了几个重要的成员函数,用于线程的等待和唤醒:

名称描述
notify_one()唤醒一个正在等待的线程。
notify_all()唤醒所有正在等待的线程。
wait(lock)在持有 lock 的情况下等待,直到被唤醒。
wait_for(lock, timeout)在持有 lock 的情况下等待一段时间,直到被唤醒或超时。
wait_until(lock, time_point)在持有 lock 的情况下等待到指定时间点,直到被唤醒或超时。

使用技巧

避免虚假唤醒

在使用 std::condition_variable 进行等待时,存在虚假唤醒的可能性,即即使没有调用 notify_one()notify_all(),线程也有可能被唤醒。为了避免这种情况,建议在等待条件时使用 predicate 进行判断。predicate 是一个函数或函数对象,用于检查条件是否满足。例如:

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

void consumer() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return data_ready; }); // 使用 predicate 避免虚假唤醒
    // 执行消费操作
}

精确的通知

在进行通知时,确保在释放锁之前完成通知操作,以避免通知操作在条件变量被销毁之后导致程序崩溃的情况。例如:

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

void producer() {
    {
        std::lock_guard<std::mutex> lock(mtx);
        data_ready = true;
    }
    cv.notify_one(); // 确保在释放锁之前完成通知操作
}

实战案例

场景一:多线程等待数据准备就绪

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

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

void worker(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return data_ready; }); // 等待数据准备就绪
    std::cout << "Worker thread " << id << ": Data is ready." << std::endl;
}

void prepare_data() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟生产数据的耗时操作
    {
        std::lock_guard<std::mutex> lock(mtx);
        data_ready = true;
    }
    cv.notify_all(); // 通知所有等待的线程数据已经准备就绪
}

int main() {
    const int num_threads = 5;
    std::thread workers[num_threads];
    
    for (int i = 0

; i < num_threads; ++i) {
        workers[i] = std::thread(worker, i);
    }

    std::thread data_preparer(prepare_data);

    for (int i = 0; i < num_threads; ++i) {
        workers[i].join();
    }

    data_preparer.join();

    return 0;
}

在这个示例中,有 5 个工作线程等待数据准备就绪。一旦数据准备就绪,调用 notify_all() 唤醒所有等待的线程。

注意事项

  • 虚假唤醒std::condition_variable 中的等待方法可能会出现虚假唤醒,即即使没有调用 notify_one()notify_all(),线程也有可能被唤醒。因此,建议在等待条件时使用 predicate 进行判断,避免虚假唤醒带来的问题。

总结

std::condition_variable 是 C++ 并发编程中重要的同步原语之一,用于线程间的通信和同步。通过合理地使用 std::condition_variable,可以有效地实现多线程之间的协调和同步,提高程序的并发性能和可靠性。

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值