C++多线程学习笔记07(条件变量)

一、条件变量std::condition_variable、wait()、notify_one()
wait():用来等待一个东西
如果第二个参数lambda表达式返回 true ,直接返回,互斥量锁住;
如果第二个参数lambda表达式返回false ,wait() 将互斥量解锁,并堵塞到本行;直到某个线程调用notify_one()成员函数为止 将wait()堵塞状态唤醒 wait开始干活。

1.wait()不断尝试重新获取互斥量锁,如果获取不到,流程卡到此处,如果获取到,走下
2.上锁(获取到锁等于上锁)
2.1 如果wait有第二个参数lambda表达式,就判断参数表达式。如果返回false,wait() 将解锁互斥量,并堵塞到本行,等待notify_one()唤醒。如果返回为true,wait返回,流程往下走,此时互斥锁是锁着的
2.3如果没有第二个参数,wait返回,流程往下走。my_cond.wait(sbguard1)直接为false堵塞。
二、notify_all() 唤醒所有线程的wait()

 // 线程6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>

class A {
public:
	//把收到的消息(玩家命令)写入到一个队列线程
	void inMsgRecvQueue()
	{
		for (int i = 0; i<10000; i++)
		{
				cout << "inMesRecvQueue()执行,插入元素" << i << endl;
				std::unique_lock<std::mutex> sbguard1(my_mutex1);
				msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队
				//假如outMsgRecvQueue()正在处理一个事务,需要一段时间,而不是卡在wait()那里等待,此时notify_one调用无效果
				my_cond.notify_one(); //尝试吧wait()唤醒 只能唤醒一个  
				//my_cond.notify_all();
		}
	}
	//把数据从消息队列中取出的线程
	void outMsgRecvQueue()
	{
		int command = 0;
		while (true)
		{
			std::unique_lock<std::mutex> sbguard1(my_mutex1);
			my_cond.wait(sbguard1, [this] {                         //一个lambda 可调用对象
				if (!msgRecvQueue.empty())
					return true;
				return false;
			});
			
			//流程走到这,这个互斥锁一定是锁着的  同时msgRecvQueue至少有一条数据
			command = msgRecvQueue.front();
			msgRecvQueue.pop_front();
			cout << "************outMsgRecvQueue()执行,取出一个元素=" << command << "thread ID = " << std::this_thread::get_id() << endl;
			sbguard1.unlock();//因为unique_lock的灵活性,unlock随时解锁
			/*
			处理其他程序需要100ms
			*/
		}
	}
private:
	list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
	mutex my_mutex1;//创建互斥量
	std::condition_variable my_cond;//生成一个条件变量对象
};
int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用  避免复制
	thread myOutMsgObj1(&A::outMsgRecvQueue, &myobj);
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myOutMsgObj.join();
	myOutMsgObj1.join();
	myInMsgObj.join();
	cout << "主线程结束" << endl;
    return 0;
}


上一篇:初识Java并发编程


下一篇:32位程序获取32/64位进程文件地址通用方法