IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++并发与多线程---学习笔记(5)condition_variable、wait、notify_one、notify_all -> 正文阅读

[C++知识库]C++并发与多线程---学习笔记(5)condition_variable、wait、notify_one、notify_all


一、条件变量condition_variable、wait()、notify_one()

1)condition_variable

  • std::condition_variable实际使用一个类,是一个和条件相关的一个类,说白了就是等待一个条件达成,这个类需要和互斥量来配合工作

2)wait()

  • 该函数是用来等待要处理的事情
#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
		}
		return;
	}

	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);
			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
		}	
	}
private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

int main() {

	example ex;
	thread out(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread in(&example::messagein, &ex);
	out.join();
	in.join();

	cout << "主线程运行" << endl;
	system("pause");
	return 0;
}
  • wait()函数参数的讲解以及用法:

  • 1、如果第二个参数lambda表达式返回值是true,那么wait()直接返回,继续执行下面的代码

  • 2、如果第二个参数lambda表达式返回值是false,那么wait()将解锁互斥量,并阻塞到本行,那阻塞到什么时候呢?阻塞到其他某个线程调用notify_one()成员函数为止

  • 3、如果没有第二个参数,代码中mycond.wait(guard)那么就跟第二个参数lambda表达式返回false效果一样,wait()将解锁互斥量,并阻塞到本行,阻塞到其他某个线程调用notify_one()成员函数为止

  • 4、当其他线程用notify_one()将本wait(原来是阻塞/堵塞)的状态唤醒后,wait就开始恢复干活,恢复后wait干什么

    • a):wait()不断的尝试重新获取互斥量,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了锁(等于加了锁),那么wait就继续执行b)
    • b):
      • b.1)如果wait有第二个参数(lambda),就判断这个lambda表达式,如果lambda表达式为false,那么wait又对互斥量解锁,然后又休眠这里等待再次被notify_one()唤醒
      • b.2)如果lambda表达式为true,则wait返回,流程走下来(此时互斥量被锁着)
      • b.3)如果wait没有第二个参数,则wait返回,流程走下来

3)notify_one()

  • 该函数用来唤醒wait()
class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
			mycond.notify_one();//尝试把wait()的线程唤醒,执行完这行,那么messageout()里边的wait就会唤醒
		}
		return;
	}
	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);

			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
			//流程只要能走下来这里,互斥锁一定是锁住,同时num至少是有一条数据的
			command = num.front();
			num.pop_front();
			cout << "messageout()执行,取出一个元素:" << command <<",thread_id:"<<this_thread::get_id()<< endl;
			guard.unlock();//临时解锁,(unique_lock的灵活性,所以我们可以随时的unlock,以免锁住太长时间)
			//执行一些具体动作,需要100毫秒的处理时间
			//。。。。。。
		}
	}
private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

二、notify_one()与notify_all()区别

  • notify_one():通知一个线程的wait()

  • notify_all():通知所有线程的wait()

    当有多个线程使用wait()时,notify_one()一个一个这样唤醒会影响运行效率,因此notify_all()会比notify_one()好用

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

class example {
public:
	void messagein() {
		for (int i = 0; i < 10000; i++)
		{
			unique_lock<mutex>guard(mymutex);
			cout << "messagein(),服务器收集数据数量:" << i << endl;
			num.push_back(i);
			mycond.notify_all();

		}
		return;
	}
	void messageout() {
		int command = 0;
		while (true)
		{
			std::unique_lock<mutex>guard(mymutex);
			mycond.wait(guard, [this] {
				if (!num.empty()) {
					return true;
				}
				return false;
			});
			//流程只要能走下来这里,互斥锁一定是锁住,同时num至少是有一条数据的
			command = num.front();
			num.pop_front();
			cout << "messageout()执行,取出一个元素:" << command <<",thread_id:"<<this_thread::get_id()<< endl;
			guard.unlock();//临时解锁,(unique_lock的灵活性,所以我们可以随时的unlock,以免锁住太长时间)

			//执行一些具体动作,需要100毫秒的处理时间
			//。。。。。。

		}
			
	}

private:
	list<int>num;
	mutex mymutex;
	condition_variable mycond;//生成一个条件变量对象
};

int main() {
	example ex;
	thread out(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread out1(&example::messageout, &ex);//第二个参数是 引用,保证线程里用的是同一个对象ex,(防止拷贝新的对象)
	thread in(&example::messagein, &ex);
	out.join();
	out1.join();
	in.join();

	cout << "主线程运行" << endl;
	system("pause");
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-13 11:45:37  更:2021-08-13 11:46:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 8:04:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码