栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++11多线程---条件变量

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++11多线程---条件变量

一、条件变量std::condition_variable、wait()、notify_one()。

条件变量在多线程中的应用场景:假设现在有两个线程

  • 线程A:等待一个条件满足
  • 线程B:专门往消息队列中扔消息(数据)

线程A等待一个条件,线程B满足这个条件之后触发先线程A,然后线程A从等待的这个位置继续运行。

std::condition_variable是一个和条件相关的类,说白了就是等待一个条件达成,这个类需要和互斥量来配合工作,用的时候我们需要生成这个类的对象。

具体工作流程:在线程A用wait来等一个东西,如果第二参数lambda表达式返回值是false,那么wait()将解锁互斥量,并堵塞本行,堵塞到线程调用notify_one()成员函数为止;如果wait()没有第二参数,那么就跟第二参数lambda函数返回false效果一样wait()解锁sbguard,并堵塞本行,堵塞到线程B调用notify_one()成员函数为止。 当wait()恢复干活时,会不断尝试重新获取互斥量锁,获取不到就会卡在wait()不断获取,直到拿到锁然后上锁。

//
// Created by yangjq on 22-7-7.
//
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

class A{
public:
    //把玩家命令收到一个队列的线程
    void inMsgRecvQueue(){
        for(int i = 0; i < 100000; ++i){
            cout << "inMsgRecvQueue" << i << endl;
            std::unique_lock sbguard(my_mutex1);
            //拿到了锁
            msgRecvQueue.push_back(i);//数字i就是玩家收到的命令
            cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;
            my_cond.notify_one();//尝试把wait()线程唤醒,执行完这行,out里的wait就会被唤醒
        }
    }


    //数据从消息队列中取出的线程
    void outMsgRecvQueue(){
        int command = 0;
        while(true){
            std::unique_lock sbguard(my_mutex1);
            //用wait来等一个东西
            //如果第二参数lambda表达式返回值是false,那么wait()将解锁互斥量,并堵塞本行
            //堵塞到其他某个线程调用notify_one()成员函数为止
            //如果wait()没有第二参数,那么就跟第二参数lambda函数返回false效果一样
            //wait()解锁sbguard,,并堵塞本行,堵塞到其他某个线程调用notify_one()成员函数为止
            //当wait()恢复干活时,会不断尝试重新获取互斥量锁
            my_cond.wait(sbguard, [this]{//一个lambda就是一个可调用对象
                if(!msgRecvQueue.empty()){
                    return true;
                }
                return false;
            });
            //流程只要能走到这里来,互斥锁一定时锁着的
            command = msgRecvQueue.front();//返回前面的元素
            msgRecvQueue.pop_front();
            cout << "outMsgRecvQueue()执行,取出一个元素!" << command << endl;
            sbguard.unlock();
        }


private:
    //容器,专门用于存储玩家发送过来的命令
    std::list msgRecvQueue;
    std::mutex my_mutex1;
    std::condition_variable my_cond;
};

int main()
{
    //用成员函数作为线程函数的方法来写线程
    A myobja;
    std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobja);
    std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);
    myInMsgObj.join();
    myOutMsgObj.join();

    cout << "main end !" << endl;
    return 0;
}

二、notify_all()

notify_one()只能通知一个线程,notify_all()可以通知多个线程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009162.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号