本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
C++在多线程中使用condition_variable实现wait
BilyLiang · 155浏览 · 发布于2022-09-20 +关注

这篇文章主要介绍了C++中的condition_variable中在多线程中的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

前言

有这样的需求

一个线程需要等待另一个线程执行完毕之后它才会继续向下执行,这该如何实现? condition_variable类中实现了wait方法

wait()

  • 可以接受两个参数,其中第一个参数是锁对象,第二个参数是lambda表达式,其中的lambda表达式的返回值要是bool类型

  • 也可接受一个参数,仅仅接受锁对象

#include<iostream>
#include<mutex>
#include<list>
#include<thread>
using namespace std;
class Obj
{
private:
    list<int> myList;
    condition_variable var;
    mutex tex;
public:
    bool popFromList(int & comb)
    {
        if (!myList.empty()) {
            unique_lock<mutex> cur(tex);
            if (!myList.empty())
            {
                comb = myList.front();
                myList.pop_front();
                return true;
            }
        }
        return false;
    }
    void inToList()
    {
        for (int i = 0; i < 100; i++)
        {
            unique_lock<mutex> cur(tex);
            myList.push_back(i);
            cout << this_thread::get_id() << "正在向list中添加数据>; " << i << endl;
            var.notify_one();
        }
    }
    void outFromList()
    {
        while(true)
        {
            unique_lock<mutex> cur(tex);
            var.wait(cur, [this] {
                if (!myList.empty())
                    return true;
                return false;
                });
            int comb = myList.front();
            myList.pop_front();
            cout << this_thread::get_id() << "正在取出数据>: " << comb << endl;
        }
    }
};
int main()
{
    Obj obj;
    thread thread1(&Obj::outFromList, &obj);
    thread thread2(&Obj::inToList, &obj);
    thread1.join();
    thread2.join();
    cout << "这里是主线程" << endl;
}

线程1执行到wait函数时,会执行lambda表达式

返回值为false时,这个线程就会将锁打开,将该线程压入到栈中,执行下一个线程 下一个线程执行完毕之后执行notify_one后就会返回到该线程,继续执行lambda表达式

返回值为true时就尝试获得锁

获得锁后继续执行下面的语句

没有获得锁就继续卡在wait等待获取到锁

返回值为false时,继续将锁打开,线程压入栈,执行下一个线程

返回值为true时,线程继续执行

运行结果可能是一个线程执行完毕另一个线程再执行

这不就是顺序执行吗?

其实并不是这样的

notify_one()

唤醒wait()函数,当前所再的线程尝试获得锁

某个线程执行完notify_one函数后,会返回到另一个线程中的wait函数处,并将其"唤醒",让其继续执行,自己的线程和wait线程都尝试获得锁来进行下一步执行

不是顺序执行的解释

  • 当wait函数后面有很多语句要执行,但是再此之前wait所在的线程函数中就已经将锁进行释放了,那么notify_one的“唤醒”就不在生效,两个线程都尝试获得锁,但是wait所在的线程有很多语句要执行,耗时高,那么很有可能notify_one所在的线程就再次获得了锁,进行下一步操作。

  • 这样就不一定是顺序执行的宏观表现了

#include<iostream>
#include<mutex>
#include<list>
#include<thread>
using namespace std;
class Obj
{
private:
    list<int> myList;
    condition_variable var;
    mutex tex;
public:
    bool popFromList(int & comb)
    {
        if (!myList.empty()) {
            unique_lock<mutex> cur(tex);
            if (!myList.empty())
            {
                comb = myList.front();
                myList.pop_front();
                return true;
            }
        }
        return false;
    }
    void inToList()
    {
        for (int i = 0; i < 1000; i++)
        {
            cout << this_thread::get_id() << "正在向list中添加数据>; " << i << endl;
            unique_lock<mutex> cur(tex);
            myList.push_back(i);
            var.notify_one();
        }
    }
    void outFromList()
    {
        while(true)
        {
            unique_lock<mutex> cur(tex);
            var.wait(cur, [this] {
                if (!myList.empty())
                    return true;
                return false;
                });
            int comb = myList.front();
            myList.pop_front();
            cur.unlock();
            cout << this_thread::get_id() << "正在取出数据>: " << comb << endl;
            chrono::seconds tim(2);
            this_thread::sleep_for(tim);
            cout <<this_thread::get_id() <<  "睡眠两秒后执行" << endl;
        }
    }
};
int main()
{
    Obj obj;
    thread thread1(&Obj::outFromList, &obj);
    thread thread2(&Obj::inToList, &obj);
    thread1.join();
    thread2.join();
    cout << "这里是主线程" << endl;
}

如图所示,在notify_one线程执行835次循环后,wait所在的线程才获得了锁,继续执行

在此之前的所有notify_one的唤醒操作都是无效的。

然后在notify_one线程执行完毕之后,wait再次获得了锁,继续向下执行

notify_all()

顾名思义,是“唤醒”所有的wait函数线程,但是并不是都一起运行,因为他们要进行锁的请求,仅仅只能由一把锁存在,只有获得锁并且lambda表达式返回结果为true的线程才能继续执行


c++

相关推荐

PHP实现部分字符隐藏

沙雕mars · 1326浏览 · 2019-04-28 09:47:56
Java中ArrayList和LinkedList区别

kenrry1992 · 909浏览 · 2019-05-08 21:14:54
Tomcat 下载及安装配置

manongba · 972浏览 · 2019-05-13 21:03:56
JAVA变量介绍

manongba · 963浏览 · 2019-05-13 21:05:52
什么是SpringBoot

iamitnan · 1088浏览 · 2019-05-14 22:20:36
加载中

0评论

评论
我是湖南最靓仔的那条仔,希望来到这里能够交道志同道合的朋友,一起学习,不断进步!!!
分类专栏
小鸟云服务器
扫码进入手机网页