一、条件变量的引入
std::condition_variable 解决了死锁并且控制的资源的访问顺序二避免不必要的等待。当互斥操作不够用而引入的。比如,线程可能需要等待某个条件为真才能继续执行,而一个忙等待循环中可能会导致所有其他线程都无法进入临界区使得条件为真时,就会发生死锁。所以,condition_variable实例被创建出现主要就是用于唤醒等待线程从而避免死锁。std::condition_variable的 notify_one()用于唤醒一个线程;notify_all() 则是通知所有线程。
二、下面是一个引用的例子
假设想实现一个简单的消费者生产者模型,一个线程往队列中放入数据,一个线程往队列中取数据,取数据前需要判断一下队列中确实有数据,由于这个队列是线程间共享的,所以,需要使用互斥锁进行保护,一个线程在往队列添加数据的时候,另一个线程不能取,反之亦然。
一般的:
std::deque<int> q; std::mutex mu; void function_1() { int count = 10; while (count > 0) { std::unique_lock<std::mutex> locker(mu); q.push_front(count); std::cout << "t1 put a value : " << count << std::endl; locker.unlock(); std::this_thread::sleep_for(std::chrono::seconds(1)); count--; } } void function_2() { int data = 0; while (data != 1) { std::unique_lock<std::mutex> locker(mu); if (!q.empty()) { data = q.back(); q.pop_back(); locker.unlock(); std::cout << "t2 got a value from t1: " << data << std::endl; } else { locker.unlock(); } } } int main() { std::thread t1(function_1); std::thread t2(function_2); t1.join(); t2.join(); return 0; }
std::this_thread::sleep_for(std::chrono::seconds(1));表示延时1s,所以这个生产的过程是很慢的;function_2函数是消费者,存在着一个while循环,只有在接收到表示结束的数据的时候,才会停止,每次循环内部,都是先加锁,判断队列不空,然后就取出一个数,最后解锁。所以说,在1s内,做了很多无用功!这样的话,单核CPU占用率会很高,可能达到100%。// threadTest.cpp: 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <fstream>
#include <deque>
#include <condition_variable>
using namespace std;
std::deque<int> q;
std::mutex mu;
std::condition_variable cond;
void function_1()
{
int count = 10;
while (count>0)
{
std::unique_lock<mutex> locker(mu);
q.push_back(count);
locker.unlock();
cond.notify_all();
std::this_thread::sleep_for(chrono::seconds(1));
count--;
}
}
void funciton_2()
{
int data = 0;
while (data != 1)
{
std::unique_lock<mutex> locker(mu);
cond.wait(locker, [](){return !q.empty(); }); // while(q.empty()) {// Unlock mu and wait to be notified 等同写法
data = q.back();
q.pop_back();
locker.unlock();
cout << "t2 get a value form t1 " << data << endl; }
}
int main() {
thread t1(function_1);
thread t2(funciton_2);
t1.join();
t2.join();
std::getchar();
return 0; }