iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++在多线程中使用condition_variable实现wait
  • 514
分享到

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

2024-04-02 19:04:59 514人浏览 泡泡鱼
摘要

目录前言wait()notify_one()notify_all()前言 有这样的需求 一个线程需要等待另一个线程执行完毕之后它才会继续向下执行,这该如何实现? condition_

前言

有这样的需求

一个线程需要等待另一个线程执行完毕之后它才会继续向下执行,这该如何实现? 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内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++在多线程中使用condition_variable实现wait

本文链接: https://www.lsjlt.com/news/167927.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么计算字符串长度
    在C语言中,可以使用内置的strlen()函数来计算字符串的长度。该函数位于string.h头文件中。以下是一个示例代码: #inc...
    99+
    2024-05-14
    c语言
  • c语言怎么判断三个数的大小
    可以通过比较三个数之间的大小关系来判断它们的大小。以下是一个示例代码: #include <stdio.h> int ...
    99+
    2024-05-14
    c语言
  • c++排序函数sort怎么使用
    在C++中,使用sort函数对容器中的元素进行排序,可以按照默认的升序排列,也可以自定义排序规则。 下面是一个简单的例子,对一个ve...
    99+
    2024-05-14
    c++
  • c++中string的compare函数怎么使用
    在C++中,可以使用string的compare函数来比较两个string对象的大小。该函数的原型如下: int compare(c...
    99+
    2024-05-14
    c++
  • c++中string的compare函数有什么用
    c++中string的compare函数用于比较两个字符串的大小关系。该函数返回一个整数值,表示两个字符串的比较结果。 具体来说,如...
    99+
    2024-05-14
    c++
  • c++中print函数的功能有哪些
    在C++中,通常使用std::cout来进行输出操作,而不是使用print函数。std::cout是C++标准库中的一个输出流对象,...
    99+
    2024-05-14
    c++
  • c语言数据结构怎么使用
    在C语言中,数据结构可以通过定义结构体来实现。以下是一些常见的数据结构的使用方法示例: 链表: #include <std...
    99+
    2024-05-14
    c语言
  • c++中print函数的用法是什么
    在C++中没有内置的print函数,但可以使用cout来输出内容到控制台。cout是C++标准库中的一个输出流对象,可以使用<...
    99+
    2024-05-14
    c++
  • c++中concept的用法是什么
    在C++20中,Concept是一种新的语言特性,用于定义类型要求和约束。Concept可以被用来约束函数模板、类模板和普通函数的参...
    99+
    2024-05-14
    c++
  • c++中concept的作用是什么
    在C++中,concept的作用是定义一种通用的约束,用于限制模板参数的类型范围。通过使用concept,可以在编译时对模板参数进行...
    99+
    2024-05-14
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作