C++并发编程-条件变量

背景说明

考虑这样一个场景:假设你工作了很长时间,需要先休息一下才能继续接下来的工作,接下来的工作需要在某个时间点(可能1个小时后)开始进行。你大概有以下可能的操作:

  1. 盯着闹钟,直到一个小时的时间到达
  2. 每隔一段时间看一下闹钟,直到1个小时后
  3. 设置闹钟1个小时后响铃,这样就可以把你叫醒
    这三种方案中,第一种会非常消耗精力,无法达到休息的效果,第二种方案中,如果时间间隔很小那就和方案1相差无几,如果时间间隔很大,就可能出现忘记查看闹钟的情况,而第三种方案则不需要自己主动去查看闹钟,只要被动接收闹钟响铃这个信息即可,在闹钟响铃之前,完全可以睡一觉放松一下。第三种方案正是条件变量的思想:等待某种条件满足并能够收到对应的通知。

C++中的条件变量

C++标准库中提供了条件变量的两种实现:std::condition_variable和std::condition_variable_any。两者都声明于头文件<condition_variable>中。这两种实现都需要配合std::mutex使用,其中前者仅支持std::mutex,而后者则可以使用满足互斥量最低标准的任意对象(低要求意味着需要有更大的代价)。如果没有特殊要求,一般使用前者。

下列代码是使用条件变量的一个简单例子: 用一个队列在两个线程之间传递数据,一个线程向队列中添加元素,另一个线程从队列中取出元素,这个场景中,取元素的队列需要在队列中有元素时才能工作,即需要等待队列非空这个条件满足才能开始工作。

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

std::mutex mut;
std::queue<int> data_queue;
std::condition_variable data_cond;

void data_preparation_thread()
{
    while (data_queue.size() < 10) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::lock_guard<std::mutex> lk(mut);
        data_queue.push(1);
        data_cond.notify_one();
    }
}

void data_processing_thread()
{
    while (true) {
        std::unique_lock<std::mutex> lk(mut);
        data_cond.wait(lk, []{return !data_queue.empty();});
        int data = data_queue.front();
        data_queue.pop();
        lk.unlock();
        std::cout << "processing a data from queue.\n";
    }
}

int main()
{
    std::thread thd_preparation(data_preparation_thread);
    std::thread thd_processing(data_processing_thread);
    thd_preparation.join();
    thd_processing.join();

    return 0;
}

简要说明以上代码块:准备数据的线程thd_preparation使用std::lock_guard对队列加锁,然后往队列中添加数据,之后使用notify_one()通知等待条件变量data_cond的线程已有数据可用。使用数据的线程thd_processing首先对mutex加锁,然后掉用wait()等待条件变量,第二个参数中的lambda表达式表示要等待的事件–队列非空。

这里需要说明一下wait()的实现,当调用wait()时,当前线程会检查条件是否满足(代码中的lambda表达式是否返回true),如果条件满足则直接返回,否则解锁mutex,并阻塞当前线程。当条件满足时,等待条件的线程会被其它线程调用notify_one()唤醒,线程对互斥量加锁并再次检查条件,如果条件不满足,则解锁mutex继续等待。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值