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 <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
#include <condition_variable>

using namespace std;

class A{
public:
    //把玩家命令收到一个队列的线程
    void inMsgRecvQueue(){
        for(int i = 0; i < 100000; ++i){
            cout << "inMsgRecvQueue" << i << endl;
            std::unique_lock<std::mutex> 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<std::mutex> 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<int> 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()可以通知多个线程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿巴乾

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值