C++11多线程(3)

条件变量

上一章我们介绍了如何用互斥量给线程加锁,达到保证数据,操作完整性的目的,这一章我们会介绍一个具有类似功能的类模板,条件变量

条件变量std::condition_variable
它一般被用来阻塞一个或同时阻塞多个线程,直到另一个线程去通知它,它才放弃阻塞。它一般会和互斥量一起使用。

条件变量的使用

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

using namespace std;

class A{
public:
	void Costomer(){
		for(int i = 0;i < 1000;++i){
			unique_lock<mutex> guard(my_mutex);
			goods.push_back(i);
			cout << "往物品栏里添加了一个编号为" << i << "的物品" << endl;
			cond.notify_one();  //唤醒一个wait()
		}
	}
	void Provider(){
		while(true){
			unique_lock<mutex> gurad(my_mutex);
			//wait用来等待条件变量的反应
			cond.wait(guard,[this]{		//条件为假则阻塞
				if(!goods.empty()){
					return true;
				}else return false;
			}
			cout << "消费者买走物品,物品编号是: " << goods.front() << endl;
			goosd.pop();
		}
	}
private:
	//容器,用来表示商品栏
	queue<int> MsgRecQue;
	//定义一个互斥量
	mutex my_mutex;
	//定义一个条件变量
	condition_variable cond;
};

int main(){
	A myobj;
	thread obj1(&A::Provider,&myobj);  //第二个参数是引用可以保证两个线程使用的是同一个对象
	thread obj2(&A::Costomer,&myobj);
	obj1.join();
	obj2.join();
	return 0;
}

运行结果:

函数简析

notify_once():条件变量.notify_once(): 它用来唤醒一个wait,并检查它是否符合某种条件(wait的第二个参数)(有可能导致死锁,例如我们把上面的!goods.empty()改成goods,empty())

notify_all():条件变量.notify_all(): 它和上面用法类似,但它可以唤醒多个wait;

wait():条件变量.wait(mutex互斥量,【一个bool型返回值的函数对象(我用的lambda)】);【】为可选参数;
当其他线程用notifiy_once()将wait()【正在阻塞的状态】唤醒时,它会不断尝试获取互斥量锁,如果获取不到,它将继续阻塞在这里继续尝试获取锁,如果获取到了锁,它将继续执行下面的语句

wait() 的参数:
当它有两个参数的时候:

  1. 第二个参数返回true: wait将直接返回。并执行下面的语句
  2. 第二个参数返回false: wait将解锁互斥量,并堵塞到本行,等待条件为真

当它只有一个参数时,它的作用和第二个参数返回false类似;

其他函数

wait_for(); //阻塞当前线程,直到条件变量被唤醒或超时
wait_until(); //阻塞当前线程,直到条件变量被唤醒或到了一定时段

总结

条件变量一般和互斥量组合使用,互斥量一定要有unlock()函数,(尝试过用lock_gurad来做互斥量,但它显示没有重载该函数,估计就是因为这个原因);

它是一种线程同步原语,能保证操作和数据的一致性,用不好也会有死锁。

它相比单纯用互斥量可以减少每次provider轮询抢锁的花销(别人notify我才去尝试抢锁), 效率会有一定提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值