一、条件变量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; }