C++ 中条件变量 std::condition_variable 的使用

背景

在 C++ 中使用一个可调用对象构造一个 std::thread 对象,即可创建一个线程;使用互斥量 std::mutex 来确保多个线程对共享数据的读写操作的同步问题。

条件变量

在多线程的使用场景中,除了涉及到共享数据读写的同步问题,还会遇到线程的执行顺序同步的情况,即:一个线程需要等另一个线程执行完成后才能执行。
若等待的线程通过 while 循环不断的判断当前条件是否满足也可以达到目的,但 while 死循环会特别的占用 CPU 资源。
假如在等待的线程在条件不满足时一直阻塞到那里,一旦条件满足则唤醒它继续执行代码,此时就需要用到条件变量。

std::condition_variable

条件变量可以理解为是一种信号通知机制,一个线程负责发送信号,其他线程等待该信号的触发。
std::condition_variable 是 C++ 中的条件变量类,定义在头文件 #include “condition_variable” 中,该类需要和互斥量来一起配合工作,但std :: condition_variable 仅适用于 std::unique_lock。

condition_variable 的使用

①.wait():等待条件的达成,若条件不满足会阻塞在本行,但并不占用 CPU。
程序执行到 wait 函数的时候会先在此阻塞,然后解锁互斥量,那么其他线程在拿到锁以后就会往下运行,当运行到 notify_one 函数的时候,就会唤醒 wait 函数来不断尝试获取互斥量锁,如果获取不到就卡在这里等待获取,如果获取到了,那么流程继续执行。

如果 wait 有第二个参数,就循环判断该 lambda 表达式的值,如果返回 false 则对互斥量解锁,然后休眠并等待再次被唤醒;如果返回 true,则 wait 返回,代码继续执行,此时互斥量已被锁住。
如果 wait 没有第二个参数,则等同于 lambda 表达式返回 false 。

②.notify_one() :唤醒一个进入阻塞或者等待的线程。

③.notify_all():唤醒所有等待的 wait() ,但是最终能抢夺锁的只有一个线程。

代码示例

#include "thread"
#include "iostream"
#include "queue"
#include "condition_variable"
#include <mutex>
using namespace std;
​
mutex m_mutex;
condition_variable cv;
bool isok = false;
void workThread()
{
  { 
    unique_lock<mutex> locker(m_mutex);
    cout << "worker 线程锁住互斥量" << endl << endl;
    cout << "worker 线程进入 wait,解锁互斥量" << endl << endl;
    cv.wait(locker, []() { return isok; });//解锁互斥量,并阻塞等待
  }
  cout << "worker 线程被唤醒" << endl << endl;
  cout << "worker 线程锁住互斥量" << endl << endl;
  cout << "worker 线程开始工作......" << endl << endl;
}
int main()
{
  thread worker(workThread);
  {
    unique_lock<mutex> locker(m_mutex);//阻塞等待 worker 线程解锁互斥量
    cout << "主线程锁住互斥量" << endl << endl;
    cout << "主线程设置 wait 条件达成" << endl << endl;
    isok = true;
  }
  cout << "主线程唤醒 worker 线程 " << endl << endl;
  cv.notify_one();
​
  worker.join();
  system("pause");
   return 0;
}

执行结果如下:
在这里插入图片描述
在这里插入图片描述

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值