C++并行开发8-condition_variable、wait、notify_one、notify_all

FengLY Lv3

std::condition_variable

condition_variable实际上是一个类,说白了就是等待一个条件的达成

  • notify_one(); 尝试把wait的线程唤醒

  • wait() 用来等一个东西 如果第二个参数返回true,那么wait()直接返回,并继续执行 如果第二个参数返回false,那么wait()将解锁互斥量,并堵塞到本行一直堵塞到某一个线程调用notify_one为止; 如果wait()没有第二个参数,my_cond(sbguard1);那么就和第二个参数lambda直接返回false一样 wait()将解锁互斥量,并堵塞到本行,直到某一个线程调用notify_one成员函数为止

  • 当其他线程用notify_one之后,wait就开始干活。干什么活呢? a) wait()不断的尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了锁,那么流程就继续 b) 上锁(实际获取到了锁就相当于上锁 ) b.1) 如果表达式为false,那wait又对互斥量解锁,然后又休眠,等待再次被notify_one()唤醒 b.2) 如果lambda表达式为true,则wait返回,流程可以继续执行(此时互斥量已被锁住)。 b.3) 如果wait没有第二个参数,则wait返回,流程走下来

    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;

    //调用类对象的成员函数的方式来创建线程
    class A {
    public:
    void inMsgRecvQueue()
    {
    for (int i = 0; i < 10000; i++) {
    cout << “inMsgRecvQueue执行,插入一个元素: “ << i << endl;
    std::unique_lockstd::mutex sbguard1(my_mutex1); //尝试拿到锁头
    msgRecvQueue.push_back(i);
    my_cond.notify_one(); //尝试把wait的线程唤醒
    // …执行其他代码
    }
    }

    void outMsgRecgQueue() {
    int commond = 0;
    while (true) {
    std::unique_lockstd::mutex sbguard1(my_mutex1);
    //wait() 用来等一个东西
    // 如果第二个参数返回true,那么wait()直接返回
    // 如果第二个参数返回false,那么wait()将解锁互斥量,并堵塞到本行
    // 一直堵塞到某一个线程调用notify_one为止;
    // 如果wait()没有第二个参数,my_cond(sbguard1);那么就和第二个参数lambda直接返回false一样
    // wait()将解锁互斥量,并堵塞到本行,直到某一个线程调用notify_one成员函数为止
    // 当其他线程用notify_one之后,wait就开始干活。干什么活呢?
    // a) wait()不断的尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了锁,那么流程就继续
    // b) 上锁(实际获取到了锁就相当于上锁 )
    // b.1) 如果表达式为false,那wait又对互斥量解锁,然后又休眠,等待再次被notify_one()唤醒
    // b.2) 如果lambda表达式为true,则wait返回,流程可以继续执行(此时互斥量已被锁住)。
    // b.3) 如果wait没有第二个参数,则wait返回,流程走下来
    my_cond.wait(sbguard1, [this] {
    if (!msgRecvQueue.empty())
    return true;
    return false;
    });

    //流程走到这里,互斥锁一定是被锁着的, 同时是最少有一条数据的
    commond = msgRecvQueue.front();
    msgRecvQueue.pop_front();
    sbguard1.unlock();
    cout << “outMsgRecgQueue 执行, 取出一个元素” << commond << endl;
    }
    }
    private:
    list msgRecvQueue; //消息队列
    std::mutex my_mutex1;// 创建一个互斥量
    std::condition_variable my_cond; //生成一个条件对象
    };

    int main()
    {
    //条件变量condition_variable、wait、notify_one、notify_all
    //线程A,等待一个条件满足
    //线程B,专门向消息队列中扔数据
    //std::condition_variable实际上是一个类,说白了就是等待一个条件的达成
    //这个类需要和互斥量配合使用

    A myobja;
    std::thread myOutnMsgObj(&A::outMsgRecgQueue, &myobja);
    std::thread myInnMsgObj(&A::inMsgRecvQueue, &myobja);

    myOutnMsgObj.join();
    myInnMsgObj.join();

    return 0;
    }

notify_one & notify_all

notify_one只是通知某一个正在wait的线程 notify_all是通知所有正在wait的线程

#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
#include <list>
#include <mutex>
using namespace std;

//调用类对象的成员函数的方式来创建线程
class A {
public:
    void inMsgRecvQueue()
    {
        for (int i = 0; i < 10000; i++) {
            cout << "inMsgRecvQueue执行,插入一个元素: " << i << endl;
            std::unique_lock<std::mutex> sbguard1(my_mutex1);  //尝试拿到锁头
            msgRecvQueue.push_back(i);
            //my_cond.notify_one();  //尝试把wait的线程唤醒
            my_cond.notify_all();  //尝试把wait的线程唤醒

            // ...执行其他代码
        }
    }

    void outMsgRecgQueue() {
        int commond = 0;
        while (true) {
            std::unique_lock<std::mutex> sbguard1(my_mutex1);
            //wait() 用来等一个东西
            // 如果第二个参数返回true,那么wait()直接返回
            // 如果第二个参数返回false,那么wait()将解锁互斥量,并堵塞到本行
            // 一直堵塞到某一个线程调用notify_one为止;
            // 如果wait()没有第二个参数,my_cond(sbguard1);那么就和第二个参数lambda直接返回false一样
            // wait()将解锁互斥量,并堵塞到本行,直到某一个线程调用notify_one成员函数为止
            // 当其他线程用notify_one之后,wait就开始干活。干什么活呢?
            // a) wait()不断的尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了锁,那么流程就继续
            // b) 上锁(实际获取到了锁就相当于上锁 )
            //    b.1) 如果表达式为false,那wait又对互斥量解锁,然后又休眠,等待再次被notify_one()唤醒
            //    b.2) 如果lambda表达式为true,则wait返回,流程可以继续执行(此时互斥量已被锁住)。
            //    b.3) 如果wait没有第二个参数,则wait返回,流程走下来
            my_cond.wait(sbguard1, [this] {
                if (!msgRecvQueue.empty())
                    return true;
                return false;
            });

            //流程走到这里,互斥锁一定是被锁着的, 同时是最少有一条数据的
            commond = msgRecvQueue.front();
            msgRecvQueue.pop_front();
            sbguard1.unlock();
            cout << "outMsgRecgQueue 执行, 取出一个元素" << commond << endl;
        }
    }

private:
    list<int> msgRecvQueue;  //消息队列
    std::mutex my_mutex1;// 创建一个互斥量
    std::condition_variable my_cond; //生成一个条件对象
};



int main()
{
    //条件变量condition_variable、wait、notify_one、notify_all
    //线程A,等待一个条件满足
    //线程B,专门向消息队列中扔数据
    //std::condition_variable实际上是一个类,说白了就是等待一个条件的达成
    //这个类需要和互斥量配合使用


    //notify_all()
    // 
    A myobja;
    std::thread myOutnMsgObj1(&A::outMsgRecgQueue, &myobja);
    std::thread myOutnMsgObj2(&A::outMsgRecgQueue, &myobja);

    std::thread myInnMsgObj(&A::inMsgRecvQueue, &myobja);

    myOutnMsgObj1.join();
    myOutnMsgObj2.join();
    myInnMsgObj.join();

    return 0;
}
  • Title: C++并行开发8-condition_variable、wait、notify_one、notify_all
  • Author: FengLY
  • Created at : 2023-06-18 22:40:09
  • Updated at : 2023-06-18 22:57:49
  • Link: https://zhouaq.com/2023/06/18/C++并行开发8-condition_variable、wait、notify_one、notify_all/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
C++并行开发8-condition_variable、wait、notify_one、notify_all