c ++ 11 multithread programação condition_variable Sessão Oito espera notify_one notify_all

 

(1) 条件 变量 std :: condition_variable, wait (), notify_one (), notify_all ()

wait () para aguardar uma coisa
            // Se o segundo argumento o valor de retorno é verdade, então esta linha vai continuar a correr para baixo.
            // Se o segundo valor do parâmetro de retorno é falsa, então a espera vai desbloquear o mutex, e tomada nesta linha
            // bloco para quando? Bloco para outro chamadas de função notify_one () até que a função
            // espera se não houver segundo argumento, o segundo argumento retorna false o mesmo efeito.
            Ao usar outras funções notify_one vai esperar acordar, e depois esperar tentará novamente para adquirir o bloqueio.
            Se você não pode obter o código do lado do cartão em espera para adquirir o bloqueio se o bloqueio é adquirido, ele vai continuar.
            1) Após a espera wake-up, eo sucesso da próxima bloqueio:
            Se o segundo argumento o valor de retorno é verdade, então esta linha vai continuar a correr para baixo.
            Se o segundo valor do parâmetro é retornos depois falsos esperar desbloqueia o mutex e entupimento na linha, à espera de despertar
            2) Se o segundo parâmetro não for esperar muito tempo como excitação, uma vez que o bloqueio é adquirido, é de esperar aqui continuar a descer.
(2) pensamento profundo do código acima
(3) notify_all ()


Condição std :: variável 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 ()

Publicado 101 artigos originais · Louvor obteve 73 · vista 120 000 +

Acho que você gosta

Origin blog.csdn.net/usstmiracle/article/details/104439351
Recomendado
Clasificación