C++在多线程中使用condition_variable实现wait

 更新时间:2022年09月20日 09:12:32   作者:君子以阅川  
这篇文章主要介绍了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++在多线程中使用condition_variable实现wait的文章就介绍到这了,更多相关C++ condition_variable内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现求最大公约数的三种方法

    C语言实现求最大公约数的三种方法

    最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。本文将为大家介绍三种方法来实现求解两个正整数的最大公约数,需要的可以参考一下
    2021-12-12
  • C++模拟实现string的示例代码

    C++模拟实现string的示例代码

    这篇文章主要为大家详细介绍了C++模拟实现string的相关资料,文中的示例代码讲解详细,对我们学习C++有一定的帮助,需要的可以参考一下
    2022-11-11
  • C语言运用函数指针数组实现计算器功能

    C语言运用函数指针数组实现计算器功能

    这篇文章主要为大家详细介绍了C语言运用函数指针数组实现计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 基于Matlab实现有雪花飘落的圣诞树的绘制

    基于Matlab实现有雪花飘落的圣诞树的绘制

    圣诞节快到了(虽然还有十天),一起来用MATLAB画个简单圣诞树叭~代码几乎取消了全部的循环,因此至少需要17b之后的版本,仅存的循环用来让树旋转起来,让雪花飘落起来,让树顶上的星光摇曳起来~感兴趣的可以试一试
    2022-12-12
  • C++内存对象布局小测试

    C++内存对象布局小测试

    这篇文章主要介绍了C++内存对象布局小测试,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • C语言字符串快速压缩算法代码

    C语言字符串快速压缩算法代码

    这篇文章主要介绍了C语言字符串快速压缩算法代码,将字符串中连续出席的重复字母进行压缩,其主要的压缩字段的格式为”字符重复的次数+字符”。有需要的小伙伴参考下吧。
    2015-03-03
  • C++ 网络连通性检测的实现方法

    C++ 网络连通性检测的实现方法

    这篇文章主要介绍了C++ 网络连通性检测的实现方法的相关资料,这里提供实例帮助大家实现这样的功能,需要的朋友可以参考下
    2017-09-09
  • C++ Queue队列类模版实例详解

    C++ Queue队列类模版实例详解

    这篇文章主要为大家详细介绍C++ Queue队列类模版实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • 指向变量的常指针与指向常变量的指针详细解析

    指向变量的常指针与指向常变量的指针详细解析

    刚接触到指针时,关于指向变量的常指针和指向常变量的指针容易混淆,所以整理下,希望能够帮助自己也帮助到大家
    2013-10-10
  • C语言 sprintf 函数详情

    C语言 sprintf 函数详情

    这篇文章主要介绍了C语言 sprintf 函数,文章主要包括sprintf 函数简介、sprintf 函数使用和简单说明了一下sprintf、fprintf、printf 函数区别,需要的朋友可以参考一下文章的具体内容
    2021-10-10

最新评论