linux编程之:条件变量std::condition_variable、wait() 、notify_one()、notify_all()

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

wait()用来等一个东西
            1、如果第二个参数返回值是true,那么这一行就继续往下运行。
            2、如果第二个参数返回值是false那么wait将解锁互斥量,并堵塞在这一行
            堵到什么时候呢?堵到其他函数调用notify_one()函数为止

如果wait没有第二个参数,那么第二个参数返回false效果一样。

 当其他函数使用notify_one将wait唤醒,然后wait就会重新尝试获取锁。如果获取不到,代码就卡在wait这边获取锁,如果获取到锁,就会继续执行
            1)唤醒wait后,并加锁成功接下来:
            如果第二个参数返回值是true,那么这一行就继续往下运行
            如果第二个参数返回值是false那么wait将解锁互斥量,并堵塞在这一行,等待唤醒
            2)如果wait没有第二个参数,只要被唤醒,那么一旦获取到锁,就从wait这边继续向下执行
(2)上述代码的深入思考
(3) notify_all()


条件变量std::condition_variable wait() 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;

}

------------------------------------------------

 
  1.  

  2.  

二、notify_all()

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值