notify_all(1)条件变量のstd :: condition_variable、待機()、notify_one()、()
事を待つ待機()
第二引数、戻り値がtrueの場合、//、このラインがダウンして実行していきます。
// 2番目のパラメータの戻り値がfalseの場合、待ち時間がミューテックスのロックを解除し、この行のプラグ
//ブロックするときに?他の機能へのブロックが機能するまで)(notify_oneを呼び出して
何の2番目の引数が存在しない場合、第二引数がfalseと同じ効果を返す//待機。
notify_one覚ますお待ちしております他の機能を使用する場合は、ロックを取得するために再試行します待ちます。
ロックが獲得された場合、あなたがロックを獲得するために待機中のカード側のコードを取得できない場合、それが継続されます。
1)ウェイクアップ待機し、次のロックの成功の後:
第二引数、戻り値がtrueの場合、この行はダウンを実行していきます。
二番目のパラメータの値がfalseその後、リターンはウェイクアップを待って、ミューテックスロックを解除待って、ラインの詰まりしている場合は
ロックが取得されると、2番目のパラメータは、ウェイクアップとして長く待たれていない場合は2)、それはここで待ってからですダウン続けます。
(2)上記のコードの深い思考
notify_all(3)()
条件変数のstd :: condition_variable待機()notify_one()
class A
{
public:
//把收到的消息放到一个队列中
void inMsgRecvQueue() //unlock()
{
for(int i=0;i<10000;++i)
{
cout<<"inMsgRecvQueue():"<<i<<endl;
std::unique_lock<std::mutex> lguard1(my_mutex1);
msgRecvQueue.push_back(i);//假设这个数字就是收到的命令,把他加入到队列中
//代码处理。。。
}
return ;
}
bool outMsgProc(int &command)
{ //双重锁定,双重检查
if(!msgRecvQueue.empty())
{ //添加这个双重锁定是因为每次不管是不是空都加锁然后再释放效率低,这样可以避免每次都加锁
std::unique_lock<std::mutex> lguard1(my_mutex1);
if(!msgRecvQueue.empty())
{
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素
return true;
}
}
return false;
}
//把数据从消息队列中取出线程
void outMsgRecvQueue()
{
int command =0;
for(int i=0;i<10000;++i)
{
bool result=outMsgProc(command);
if(result==true)
{
cout<<"outMsgRecvQueue()执行,取出一个元素"<<command<<endl;
//对消息处理
}
else
{
//消息队列为空
sleep(100);
cout<<"outMsgRecvQueue()执行,但是消息队列为空"<<i<<endl;
}
}
cout<<"end"<<endl;
}
private:
std::list<int> msgRecvQueue;//容器(消息队列)专门用于代表玩家发送的命令
std::mutex my_mutex1;//创建了一个互斥量
std::mutex my_mutex2;//创建了一个互斥量
};
int main()
{ //条件变量std::condition_variable wait() notify_one()
//线程A:等待一个条件满足
//线程B:向消息队列中放消息
A myobja;
std::thread my_out_Thread(&A::outMsgRecvQueue,&myobja);//outMsgRecvQueue为起始函数的线程
std::thread my_in_Thread(&A::inMsgRecvQueue,&myobja);//inMsgRecvQueue为起始函数的线程
outMsgRecvQueue.join();
inMsgRecvQueue.join();
cout<<"主线程收尾,正常退出"<endl;
return 0;
}
------------------------------------------------
class A
{
public:
//把收到的消息放到一个队列中
void inMsgRecvQueue() //unlock()
{
for(int i=0;i<10000;++i)
{
std::unique_lock<std::mutex> lguard1(my_mutex1);
cout<<"inMsgRecvQueue()插入一个元素:"<<i<<endl;
msgRecvQueue.push_back(i);//假设这个数字就是收到的命令,把他加入到队列中
/*
my_con.notify_one();//我们尝试把wait()唤醒,这行运行完,那么outMsgRecvQueue中的wait就会被唤醒
notify_one()通知唤醒一个线程,只能通知一个线程。
*/
my_con.notify_all();//唤醒所有处于wait状态的线程
//代码处理。。。
}
return;
}
//把数据从消息队列中取出线程
void outMsgRecvQueue()
{
int command =0;
while(true)
{
std::unique_lock<std::mutex> lguard1(my_mutex1);
//wait()用来等一个东西
//如果第二个参数返回值是true,那么这一行就继续往下运行。
//如果第二个参数返回值是false那么wait将解锁互斥量,并堵塞在这一行
//堵到什么时候呢?堵到其他函数调用notify_one()函数为止
//如果wait没有第二个参数,那么第二个参数返回false效果一样。
当其他函数使用notify_one将wait唤醒,然后wait就会重新尝试获取锁。
如果获取不到,代码就卡在wait这边获取锁,如果获取到锁,就会继续执行。
1)唤醒wait后,并加锁成功接下来:
如果第二个参数返回值是true,那么这一行就继续往下运行。
如果第二个参数返回值是false那么wait将解锁互斥量,并堵塞在这一行,等待唤醒
2)如果wait没有第二个参数,只要被唤醒,那么一旦获取到锁,就从wait这边继续向下执行。
my_con.wait(lguard1,[this]{ //一个lambda表达式,就是一个可调用对象
if(!msgRecvQueue.empty())
return true;
return false;
});
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素
cout<<"outMsgRecvQueue取出一个元素"<<std::this_thread::get_id()<<endl;
lguard1.unlcok(); //因为unique_lock的灵活性,所以可以随时解锁、免得锁太久
}
cout<<"end"<<endl;
}
private:
std::list<int> msgRecvQueue;//容器(消息队列)专门用于代表玩家发送的命令
std::mutex my_mutex1;//创建一个互斥量
std::condition_variable my_con;//创建一个条件变量对象
};
int main()
{ //条件变量std::condition_variable wait() notify_one()
//线程A:等待一个条件满足
//线程B:向消息队列中放消息
std::condition_variable实际上是一个类,是一个和条件相关的一个类。
需要等待一个条件达成,这个类需要和互斥量配合使用,需要生成一个类的对象
A myobja;
std::thread my_out_Thread(&A::outMsgRecvQueue,&myobja);//outMsgRecvQueue为起始函数的线程
std::thread my_out_Thread2(&A::outMsgRecvQueue,&myobja);
std::thread my_in_Thread(&A::inMsgRecvQueue,&myobja);//inMsgRecvQueue为起始函数的线程
outMsgRecvQueue.join();
outMsgRecvQueue2.join();
inMsgRecvQueue.join();
cout<<"主线程收尾,正常退出"<endl;
return 0;
}
二、notify_all()