好的,我们来详细探讨 C++ 中 std::condition_variable 的使用方法。条件变量是多线程同步的强大工具,常用于线程间的等待与通知机制,特别是在 生产者-消费者模型 或需要等待特定条件满足的场景中。

核心概念

  1. std::condition_variable
    用于阻塞一个或多个线程,直到另一线程修改共享变量并通知条件变量。
  2. std::mutex
    条件变量必须与互斥锁配合使用,确保对共享数据的操作是线程安全的。
  3. wait()
    线程调用 wait() 后会释放锁并阻塞,直到被其他线程唤醒。唤醒后会自动重新获取锁。
  4. notify_one() / notify_all()
    唤醒一个或所有等待中的线程。

实战示例:生产者-消费者模型

以下是一个简单的生产者-消费者示例,使用条件变量协调生产和消费操作。

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

std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue; // 共享数据缓冲区
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 data_queue.size() < MAX_SIZE; });
        
        data_queue.push(i);
        std::cout << "Produced: " << i << std::endl;
        lock.unlock();
        
        // 通知一个消费者
        cv.notify_one();
    }
}

// 消费者线程
void consumer() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        
        // 等待缓冲区非空
        cv.wait(lock, []{ return !data_queue.empty(); });
        
        int data = data_queue.front();
        data_queue.pop();
        std::cout << "Consumed: " << data << std::endl;
        lock.unlock();
        
        // 通知一个生产者
        cv.notify_one();
    }
}

int main() {
    std::thread p1(producer);
    std::thread c1(consumer);
    
    p1.join();
    c1.join();
    return 0;
}


关键点解析

  1. wait() 的谓词参数

    cv.wait(lock, []{ return !data_queue.empty(); });
    

    • 避免 虚假唤醒(Spurious Wakeup),确保条件真正满足后才继续执行。
    • 相当于:
      while (!condition) {
          cv.wait(lock);
      }
      
  2. 锁的作用域

    • 使用 std::unique_lock 灵活管理锁的生命周期。
    • wait() 前加锁,wait() 内部会自动释放锁;被唤醒后重新获取锁。
  3. 通知机制

    • notify_one():唤醒一个等待线程(效率高)。
    • notify_all():唤醒所有等待线程(适用于多个消费者/生产者)。

使用场景建议

  • 任务队列:线程池中的任务调度。
  • 事件驱动:等待外部事件(如网络数据到达)。
  • 资源限制:控制并发访问资源的最大数量。

注意事项

  1. 死锁风险
    确保所有分支路径都能正确释放锁或通知条件变量。
  2. 生命周期管理
    确保条件变量和互斥锁的存活时间覆盖所有线程的操作。

通过合理使用条件变量,可以高效实现复杂的线程协作逻辑。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐