一、条件变量概述
条件变量可以实现一个线程唤醒一个或多个其他等待中的线程,实现线程间的同步。生产者消费者模型就可以用条件变量来实现。
二、条件变量示例
源码
#pragma once
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <queue>
using namespace std;
class ConditionVariableTest
{
private:
static mutex _queueMutex;
static queue<int> _queue;
static condition_variable _queueConditionVar;
public:
void DoTest()
{
thread providerThread(Provider);
int consumerNum = 2;
thread** consumerThread = new thread*[consumerNum];
for (int i = 0; i < 2; i++)
{
consumerThread[i] = new thread(Consumer,i+1);
}
providerThread.join();
}
static void Provider()
{
for (int i = 0; ; i+=2)
{
_queueMutex.lock();
_queue.push(i);
printf("provider v=%d\n", i);
_queue.push(i+1);
printf("provider v=%d\n", i+1);
_queueMutex.unlock();
_queueConditionVar.notify_all();
this_thread::sleep_for(chrono::milliseconds(1000));//1000ms生产1个
}
}
static void Consumer(int id)
{
while (true)
{
{
//uniqueLock的作用域在大括号里,出了大括号,自动解锁
unique_lock<mutex> uniqueLock(_queueMutex); //unique_lock是对mutex的封装,如果对mutex加了锁,在unique_lock析构时(这里也就是在出了大括号时),会自动解锁mutex
_queueConditionVar.wait(uniqueLock, [] {
return !_queue.empty(); }); //条件不满足会挂起
//拿到uniqueLock的锁
//等待收到_queueConditionVar的notify,并检查wait里的条件,直到这两个条件都满足
int v = _queue.front();
_queue.pop();
printf("consumer%d v=%d\n", id, v);
}
}
}
};
mutex ConditionVariableTest::_queueMutex;
queue<int> ConditionVariableTest::_queue;
condition_variable ConditionVariableTest::_queueConditionVar;
输出
provider v=0
provider v=1
consumer1 v=0
consumer1 v=1
provider v=2
provider v=3
consumer2 v=2
consumer2 v=3
provider v=4
provider v=5
consumer2 v=4
consumer2 v=5
provider v=6
provider v=7
consumer2 v=6
consumer2 v=7
provider v=8
provider v=9
consumer2 v=8
consumer2 v=9
provider v=10
provider v=11
consumer1 v=10
consumer1 v=11