当前位置:首页 > C++ > 正文

C++条件变量详解(手把手教你掌握多线程同步利器)

C++并发编程 中,多个线程之间如何安全、高效地通信与协作是一个核心问题。而 C++条件变量std::condition_variable)正是解决这类问题的关键工具之一。本教程将从零开始,用通俗易懂的语言带你深入理解并正确使用条件变量。

C++条件变量详解(手把手教你掌握多线程同步利器) C++条件变量 多线程同步 C++并发编程 condition_variable使用教程 第1张

什么是条件变量?

条件变量是一种线程同步机制,允许一个或多个线程等待某个特定条件成立,而另一个线程在条件满足时通知等待的线程继续执行。它通常与互斥锁(std::mutex)配合使用,以避免竞态条件(race condition)。

在 C++11 及以后的标准中,条件变量由 <condition_variable> 头文件提供,主要包含两个类:

  • std::condition_variable:仅支持与 std::unique_lock<std::mutex> 一起使用,性能更优。
  • std::condition_variable_any:可与任意满足基本锁要求的类型配合使用,但开销略大。

为什么需要条件变量?

假设你有两个线程:一个生产者线程负责生成数据,一个消费者线程负责处理数据。消费者不能在没有数据时盲目轮询(浪费 CPU),而应“等待”直到有数据可用。这时,多线程同步 就显得尤为重要,而条件变量正是实现这种“等待-通知”机制的理想选择。

基本使用方法

使用 std::condition_variable 的典型步骤如下:

  1. 定义一个互斥锁(std::mutex)和一个条件变量(std::condition_variable)。
  2. 等待线程获取锁,然后调用 wait() 方法,该方法会自动释放锁并阻塞,直到被通知。
  3. 通知线程在修改共享状态后,调用 notify_one()notify_all() 唤醒等待线程。

关键函数说明:

  • wait(unique_lock& lock):阻塞当前线程,直到被通知。
  • wait(unique_lock& lock, Predicate pred):带谓词的等待,可避免虚假唤醒(推荐使用)。
  • notify_one():唤醒一个等待的线程。
  • notify_all():唤醒所有等待的线程。

完整代码示例

下面是一个经典的“生产者-消费者”模型,演示如何使用 condition_variable使用教程 中的核心技巧:

#include <iostream>#include <thread>#include <mutex>#include <condition_variable>#include <queue>#include <chrono>std::queue<int> data_queue;std::mutex mtx;std::condition_variable cv;bool finished = false;void producer() {    for (int i = 0; i < 5; ++i) {        std::this_thread::sleep_for(std::chrono::milliseconds(500));        {            std::lock_guard<std::mutex> lock(mtx);            data_queue.push(i);            std::cout << "Produced: " << i << std::endl;        }        cv.notify_one(); // 通知消费者    }    {        std::lock_guard<std::mutex> lock(mtx);        finished = true;    }    cv.notify_one();}void consumer() {    while (true) {        std::unique_lock<std::mutex> lock(mtx);        // 使用带谓词的 wait,防止虚假唤醒        cv.wait(lock, []() { return !data_queue.empty() || finished; });        if (!data_queue.empty()) {            int value = data_queue.front();            data_queue.pop();            std::cout << "Consumed: " << value << std::endl;            lock.unlock();        } else if (finished) {            break;        }    }}int main() {    std::thread t1(producer);    std::thread t2(consumer);    t1.join();    t2.join();    std::cout << "All done!" << std::endl;    return 0;}

注意事项与最佳实践

  • 始终使用带谓词的 wait():避免因操作系统调度导致的“虚假唤醒”(spurious wakeup)。
  • 先修改状态,再通知:确保在持有锁的情况下修改共享数据,然后再调用 notify,以保证一致性。
  • 不要在持有锁时执行耗时操作:这会阻塞其他线程获取锁,降低并发性能。
  • 合理选择 notify_one 还是 notify_all:若只有一个线程需要被唤醒,用 notify_one 更高效。

总结

通过本教程,你应该已经掌握了 C++条件变量 的基本原理和使用方法。它是 C++并发编程 中不可或缺的同步工具,能有效协调多线程之间的执行顺序。记住:正确使用互斥锁 + 条件变量 + 谓词,是编写安全、高效多线程程序的关键。

希望这篇 condition_variable使用教程 能帮助你迈出多线程开发的第一步!如果你觉得有用,欢迎分享给更多正在学习 多线程同步 的朋友。