深入解析 C++ 条件变量 condition_variable

2026-03-18 11:15:02 2439阅读

在多线程编程中,线程间的同步与通信是一个关键问题。C++ 标准库提供了多种工具来处理这些问题,其中条件变量 condition_variable 是一个强大且常用的工具。本文将深入探讨 C++ 条件变量 condition_variable 的原理、用法以及实际应用。

条件变量的基本概念

条件变量是一种用于线程间同步的机制,它允许线程在某个条件不满足时进入等待状态,直到其他线程通知该条件已经满足。condition_variable 通常与互斥锁(mutex)一起使用,以确保线程安全。

工作原理

条件变量的工作原理基于两个主要操作:wait()notify_one()/notify_all()

  • wait():当一个线程调用 wait() 时,它会释放持有的互斥锁,并进入等待状态。直到其他线程调用 notify_one()notify_all() 通知它,该线程才会重新获取互斥锁并继续执行。
  • notify_one():唤醒一个正在等待该条件变量的线程。
  • notify_all():唤醒所有正在等待该条件变量的线程。

条件变量的使用方法

基本示例

下面是一个简单的示例,展示了如何使用 condition_variable 实现线程间的同步:

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

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

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    // 等待条件满足
    cv.wait(lock, []{ return ready; });
    std::cout << "Worker thread is working." << std::endl;
}

void master() {
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    // 通知等待的线程
    cv.notify_one();
    std::cout << "Master thread has notified." << std::endl;
}

int main() {
    std::thread t1(worker);
    std::thread t2(master);

    t1.join();
    t2.join();

    return 0;
}

代码解释

  • std::mutex mtx:定义一个互斥锁,用于保护共享变量 ready
  • std::condition_variable cv:定义一个条件变量,用于线程间的通知。
  • bool ready:共享变量,用于表示条件是否满足。
  • worker() 函数:线程函数,使用 cv.wait(lock, []{ return ready; }) 等待条件满足。
  • master() 函数:线程函数,设置 readytrue 并调用 cv.notify_one() 通知等待的线程。

条件变量的实际应用

生产者 - 消费者模型

生产者 - 消费者模型是多线程编程中常见的问题,条件变量可以很好地解决这个问题。

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

std::mutex mtx;
std::condition_variable cv;
std::queue<int> buffer;
const int MAX_SIZE = 10;

void producer() {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待缓冲区有空间
        cv.wait(lock, []{ return buffer.size() < MAX_SIZE; });
        buffer.push(i);
        std::cout << "Produced: " << i << std::endl;
        // 通知消费者
        cv.notify_one();
    }
}

void consumer() {
    for (int i = 0; i < 20; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待缓冲区有数据
        cv.wait(lock, []{ return !buffer.empty(); });
        int item = buffer.front();
        buffer.pop();
        std::cout << "Consumed: " << item << std::endl;
        // 通知生产者
        cv.notify_one();
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);

    t1.join();
    t2.join();

    return 0;
}

代码解释

  • std::queue<int> buffer:定义一个缓冲区,用于存储生产者生产的数据。
  • const int MAX_SIZE:定义缓冲区的最大容量。
  • producer() 函数:生产者线程,使用 cv.wait(lock, []{ return buffer.size() < MAX_SIZE; }) 等待缓冲区有空间,生产数据后通知消费者。
  • consumer() 函数:消费者线程,使用 cv.wait(lock, []{ return !buffer.empty(); }) 等待缓冲区有数据,消费数据后通知生产者。

注意事项

虚假唤醒

在使用 condition_variable 时,需要注意虚假唤醒的问题。虚假唤醒是指线程在没有收到 notify_one()notify_all() 通知的情况下被唤醒。因此,在调用 wait() 时,通常需要使用带有谓词的版本,以确保条件确实满足。

锁的管理

condition_variable 必须与 std::unique_lock 一起使用,因为 wait() 函数需要在等待期间释放和重新获取锁。

总结与建议

C++ 条件变量 condition_variable 是一个强大的线程同步工具,它可以帮助我们解决多线程编程中的复杂同步问题。在使用时,需要注意以下几点:

  • 与互斥锁一起使用,确保线程安全。
  • 使用带有谓词的 wait() 函数,避免虚假唤醒。
  • 合理管理锁的生命周期,避免死锁。

通过深入理解条件变量的原理和用法,我们可以编写出更加高效、稳定的多线程程序。希望本文对你理解 C++ 条件变量有所帮助。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

目录[+]