C++11多线程(三)condition_variable、wait()、notify_one()

condition_variable

这是一个等待条件成立,然后唤醒线程的机制
wait() 等待被唤醒
notify_one()唤醒一个卡在wait处的线程
notify_all()唤醒所有卡在wait处的线程
有些线程的执行有条件限制,例如:只有在队列中有元素的情况下才执行弹出和删除元素的操作。
用法是先声明一个condition_variable 的变量conv
在线程中使用 conv.wait( para1, para2 )
第一个参数是一个unique_guard对象
第二个参数是一个可调用对象(可以是一个lambda表达式),如下所示

unique_lock<mutex> guard(m_Mutex); //先锁住
conv.wait(   guard,   [this] {return !m_Queue.empty();}   );

如果参数二返回的是true,程序继续运行。
如果是false,则解锁,然后卡住,指导被唤醒,再次锁住互斥量,重新进行判断
这个过程可以理解为:
在这里插入图片描述
下面是一个对C++11多线程(二)中的代码的改进

class A
{
	deque<int> m_Queue;
	mutex m_Mutex;
	std::condition_variable conv;
public:
	unique_lock<mutex> rtn_lock()
	{
		unique_lock<mutex> temp(m_Mutex);
		return temp;//返回局部对象,调用移动构造函数
	}
	void inMessage()
	{
		for (int i = 0; i < 100000; i++)
		{
			cout << "in  " << i << endl;
			unique_lock<mutex> guard = rtn_lock();
			m_Queue.push_back(i);
			conv.notify_one();//插入元素后就唤醒线程outMessage继续执行
		}
	}
	void outMessage()
	{
		for (int i = 0; i < 100000; i++)
		{
			int command = -1;
			while (true)
			{
				unique_lock<mutex> guard1(m_Mutex);
				conv.wait(guard1, [this] {
					if (!m_Queue.empty())return true;//如果非空,就可以对m_Queue进行接下来的操作
					return false;//如果为空,就解锁,然后等着,直到被notify_one唤醒,再次锁住互斥量,重新判断
				});
				command = m_Queue.front();
				m_Queue.pop_front();
				guard1.unlock();
				cout << "out " << command << endl;
			}
		}
	}
};
int main()
{
	A a;
	thread tobjin(&A::inMessage, std::ref(a));
	thread tobjout(&A::outMessage, std::ref(a));
	tobjin.join();
	tobjout.join();
	
	system("pause");
	return 0;
}

注意:只有当一个线程卡在wait()的时候,另一个线程的notify_one才有效
唤醒之后并不一定就会马上执行,应为唤醒之后还要加锁,并不一定能成功加锁,可能被另一个线程先锁了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章