C++多线程std::condition_variable的使用,凭借条件变量等待条件成立

   std::condition_variable 是 C++ 标准库 <condition_variable> 头文件中提供的一个用于线程间同步的工具,它允许线程在某个条件满足时被唤醒。通常与 std::mutex 或 std::unique_lock 配合使用,在多线程编程中非常有用,比如实现生产者 - 消费者模型等场景。下面将从基本概念、工作原理、常用方法、应用场景和示例代码等方面详细介绍 std::condition_variable

基本概念

   std::condition_variable 本质上是一个同步原语,它提供了一种机制,让线程可以阻塞自己,直到另一个线程通知它某个条件已经满足。当一个线程等待条件变量时,它会释放持有的互斥锁,进入阻塞状态;当其他线程通知条件变量时,等待的线程会被唤醒,并尝试重新获取互斥锁。

工作原理

  1. 等待操作:当一个线程调用 std::condition_variable 的 wait 方法时,它会自动释放当前持有的互斥锁,并进入阻塞状态。此时,其他线程可以获取该互斥锁并修改共享状态。
  2. 通知操作:当另一个线程修改了共享状态,并且满足了某个条件时,它可以调用 std::condition_variable 的 notify_one 或 notify_all 方法。notify_one 会唤醒一个等待在该条件变量上的线程,而 notify_all 会唤醒所有等待在该条件变量上的线程。
  3. 重新锁定:被唤醒的线程会尝试重新获取之前释放的互斥锁,一旦获取成功,它会继续执行后续的代码。

常用方法

  • wait 系列方法
    • void wait( std::unique_lock<std::mutex>& lock );:阻塞当前线程,直到收到通知。调用该方法时,线程会自动释放 lock 持有的互斥锁,并进入等待状态;当收到通知并重新获取互斥锁后,线程会继续执行。
    • template< class Predicate > void wait( std::unique_lock<std::mutex>& lock, Predicate pred );:阻塞当前线程,直到收到通知且 pred 条件为 true。该方法会在每次被唤醒时检查 pred 的返回值,如果为 false 则继续等待。
  • notify 系列方法
    • void notify_one();:唤醒一个等待在该条件变量上的线程。如果没有线程在等待,则该调用没有效果。
    • void notify_all();:唤醒所有等待在该条件变量上的线程。

应用场景

  • 生产者 - 消费者模型:生产者线程生产数据并放入缓冲区,消费者线程从缓冲区取出数据进行处理。当缓冲区为空时,消费者线程可以等待条件变量;当生产者线程放入数据后,通知消费者线程。
  • 多线程任务同步:在某些场景下,一个线程需要等待其他线程完成特定任务后才能继续执行,此时可以使用条件变量进行同步。

示例代码(生产者 - 消费者模型)

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

std::queue<int> buffer;
std::mutex mtx;
std::condition_variable notFull;
std::condition_variable notEmpty;
const int MAX_SIZE = 5;

// 生产者线程函数
void producer() {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待缓冲区不满
        notFull.wait(lock, [] { return buffer.size() < MAX_SIZE; });

        buffer.push(i);
        std::cout << "Produced: " << i << std::endl;

        // 通知消费者缓冲区非空
        notEmpty.notify_one();
    }
}

// 消费者线程函数
void consumer() {
    for (int i = 0; i < 10; ++i) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待缓冲区非空
        notEmpty.wait(lock, [] { return!buffer.empty(); });

        int value = buffer.front();
        buffer.pop();
        std::cout << "Consumed: " << value << std::endl;

        // 通知生产者缓冲区不满
        notFull.notify_one();
    }
}

int main() {
    std::thread producerThread(producer);
    std::thread consumerThread(consumer);

    producerThread.join();
    consumerThread.join();

    return 0;
}

        通过使用 std::condition_variable,实现了生产者和消费者线程之间的同步,确保了在缓冲区满时生产者线程等待,在缓冲区空时消费者线程等待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

摸鱼儿v

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

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

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

打赏作者

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

抵扣说明:

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

余额充值