最新章节 62.一起来做网站吧,怎么做新网站,地瓜互联 wordpress,云服务器有哪些平台系列文章目录 文章目录系列文章目录前言一、基本概念1.1 std::condition_variable1.2 wait()函数1.2.1 wait()带第二个参数1.2.2 wait()不带第二个参数1.2.3 当其他线程用notify_one()或notify_all#xff08;#xff09;1.3 notify函数二、代码实例总结前言
C11多线程…系列文章目录 文章目录系列文章目录前言一、基本概念1.1 std::condition_variable1.2 wait()函数1.2.1 wait()带第二个参数1.2.2 wait()不带第二个参数1.2.3 当其他线程用notify_one()或notify_all1.3 notify函数二、代码实例总结前言
C11多线程wait()和notify()的使用。 一、基本概念
1.1 std::condition_variable
private:std::condition_variable my_cond; //生成一个条件变量对象条件变量std::condition_variable、wait()、notify_one()只能通知一个outMsgRecvQueue线程。std::condition_variable实际上是一个类是一个和条件相关的一个类说白了就是等待一个条件达成。这个类需要和互斥量来配合工作用的时候我们要生成这个类的对象
1.2 wait()函数
1.2.1 wait()带第二个参数
wait()用来等一个东西,运行到这一行代码会进行判断。
//这里wait是带第二个参数的。my_cond.wait(sbguard1, [this] { //一个lambda就是一个可调用对象函数if (!msgRecvQueue.empty())return true;return false;}); msgRecvQueue.empty(),是用来判断队列是否为空自己写的函数可参考章节二代码实例 如果第二个参数lambda表达式返回值是true那wait()直接返回,不堵塞。如果第二个参数lambda表达式返回值是false那么wait()将解锁互斥量并堵塞到本行 那堵塞到什么时候为止呢 答堵塞到其他某个线程调用notify_one()或notify_all()成员函数为止 1.2.2 wait()不带第二个参数
my_cond.wait(sbguard1)那么就跟第二个参数lambda表达式返回false效果一样 wait()将解锁互斥量并堵塞到本行堵塞到其他某个线程调用notify_one()成员函数为止
1.2.3 当其他线程用notify_one()或notify_all
会将本wait原来是睡着/堵塞的状态唤醒后wait就开始恢复干活了恢复后wait干什么活 await()不断的尝试重新获取互斥量锁如果获取不到那么流程就卡在wait这里等着获取如果获取到了锁等于加了锁那么wait就继续执行b b有以下三个如果 b.1如果wait有第二个参数(lambda)就判断这个lambda表达式如果lambda表达式为false那么wait又对互斥量解锁然后又休眠在这里等待再次被notify_one唤醒 b.2如果lambda表达式为true则wait返回流程走下来此时互斥锁被锁着。 b.3如果wait没有第二个参数则wait返回流程走下来。
1.3 notify函数
//my_cond.notify_one();
my_cond.notify_all();notify_one()只能通知一个指定的线程。 notify_all()通知所有线程。
二、代码实例
#include stdio.h
#include tchar.h
#include SDKDDKVer.h
#include iostream
#include vector
#include map
#include string
#include thread
#include list
#include mutex
#include condition_variableusing namespace std;class A
{
public://把收到的消息玩家命令入到一个队列的线程void inMsgRecvQueue() //unlock(){for (int i 0; i 100000; i){std::unique_lockstd::mutex sbguard1(my_mutex1);cout inMsgRecvQueue()执行插入一个元素 i endl;msgRecvQueue.push_back(i);//假设这个数字i就是我收到的命令我直接弄到消息队列里边来//假如outMsgRecvQueue()正在处理一个事务需要一段时间而不是正卡在wait()那里等待你唤醒那么此时这个notify_one()这个调用也许就没效果//my_cond.notify_one();//我们尝试把wait()的线程唤醒执行完这行那么outMsgRecvQueue()里边的wait就会被唤醒//唤醒之后的事情后续研究my_cond.notify_all();//......//其他处理代码}return;}//把数据从消息队列中取出的线程void outMsgRecvQueue(){int command 0;while (true){std::unique_lockstd::mutex sbguard1(my_mutex1);my_cond.wait(sbguard1, [this] { //一个lambda就是一个可调用对象函数if (!msgRecvQueue.empty())return true;return false;});//流程只要能走到这里来这个互斥锁一定是锁着的。//一会再写其他的...command msgRecvQueue.front(); //返回第一个元素但不检查元素是否存在msgRecvQueue.pop_front(); //移除第一个元素但不返回cout outMsgRecvQueue()执行取出一个元素: command threadid std::this_thread::get_id() endl;sbguard1.unlock(); //因为unique_lock的灵活性所以我们可以随时的unlock解锁以免锁住太长时间//执行一些其他的动作帮助玩家抽卡抽卡需要100毫秒的处理时间//...//执行100毫秒//} //end while}private:std::listint msgRecvQueue; //容器专门用于代表玩家给咱们发送过来的命令。std::mutex my_mutex1; //创建一个互斥量一把锁头std::condition_variable my_cond; //生成一个条件变量对象
};int main()
{A myobja;std::thread myOutnMsgObj(A::outMsgRecvQueue, myobja); //第二个参数 引用才能保证线程里 用的是同一个对象std::thread myOutnMsgObj2(A::outMsgRecvQueue, myobja);std::thread myInMsgObj(A::inMsgRecvQueue, myobja);myInMsgObj.join();myOutnMsgObj.join();myOutnMsgObj2.join();return 0;
} 总结
1了解wait()的使用对锁 的影响以及第二参数有无的区别 2condition_variable、wait()、notify_one()或notify_all()如何配合工作。 3理解如何处理线程之间的交互联系