(1) 条件 变量 std :: condition_variable, wait (), notify_one (), notify_all ()
wait () para esperar una cosa
// Si el segundo argumento el valor de retorno es cierto, entonces esta línea seguirá funcionando abajo.
// Si el segundo parámetro de valor de retorno es falsa entonces la espera será desbloquear el mutex, y el enchufe en esta línea
// bloque para cuándo? Bloquear a otra llamadas a funciones notify_one () hasta que la función
// espera si no hay un segundo argumento, el segundo argumento devuelve falso el mismo efecto.
Al utilizar otras funciones notify_one esperará a despertar, a continuación, esperar a tratar de nuevo para adquirir el bloqueo.
Si no puede obtener el código en el lado de la tarjeta a la espera de adquirir el bloqueo si se adquiere el bloqueo, continuará.
1) Después de la espera de atención, y el éxito de la próxima bloqueo:
Si el segundo argumento el valor de retorno es cierto, entonces esta línea continuará funcionando abajo.
Si el segundo valor del parámetro es luego vuelve a esperar falsas desbloquea el mutex, y la obstrucción en la línea, a la espera de despertar
2) Si el segundo parámetro no se espera siempre que despertar, una vez que se adquiere el bloqueo, es a partir de aquí la espera continuar hacia abajo.
(2) de profundidad pensamiento del código anterior
(3) notify_all ()
condición variable std :: espera 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 ()