[编程基础] C++多线程入门7-条件变量介绍
原始C++标准仅支持单线程编程。新的C++标准(称为C++11或C++0x)于2011年发布。在C++11中,引入了新的线程库。因此运行本文程序需要C++至少符合C++11标准。
7 条件变量介绍
在本文中,我们将通过示例讨论C ++ 11多线程中条件变量的用法。
7.1 条件变量
条件变量是一种事件,用于在两个或多个线程之间发出信号。一个或多个线程可以等待它发出信号,而另一个线程可以发出信号。
 C ++ 11中的条件变量所需的头文件是:
#include <condition_variable>
需要互斥锁以及条件变量。
 条件变量如何实际起作用:
- 线程1调用等待条件变量,该变量在内部获取互斥锁并检查是否满足所需条件。
 - 如果不是,则释放锁并等待条件变量发出信号(线程被阻塞)。条件变量的wait()函数以自动方式提供这两种操作。
 - 当满足条件时,另一个线程即线程2会发出条件变量信号。
 - 一旦收到条件变量的信号,等待它的线程1恢复。然后,它再次获取互斥锁,并检查与条件变量关联的条件是否真正满足或是否为上级调用。如果有多个线程在等待,那么notify_one将仅解除阻塞一个线程。
 - 如果是上级调用,则再次调用wait()函数。
 
7.2 std::condition_variable的主要成员函数
std::condition_variable的主要成员函数是:
 Wait()
 该函数使当前线程阻塞,直到信号通知条件变量或发生虚假唤醒为止。
 它自动释放附加的互斥锁,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中。当某些线程在同一条件变量对象上调用notify_one()或notify_all()时,该线程将被解除阻塞。它也可能会被虚假地解除阻塞,因此,每次解除阻塞后,都需要再次检查条件。
 回调将作为参数传递给此函数,该函数将被调用以检查它是否是虚假调用或是否实际满足条件。wait()函数重新获取互斥锁并检查是否满足实际条件。如果不满足条件,则再次自动释放附加的互斥锁,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中。
notify_one()
 如果有任何线程在同一条件变量对象上等待,则notify_one解除阻塞其中一个等待线程。
notify_all()
 如果有任何线程在相同的条件变量对象上等待,则notify_all解除所有等待线程的阻塞。
7.3 解决问题的方法
假设我们正在构建一个基于网络的应用程序。该应用程序执行以下任务,
- 与服务器进行一些握手
 - 从XML文件加载数据。
 - 对从XML加载的数据进行处理。
 
如我们所见,任务1不依赖于任何其他任务,但是任务3依赖于任务2。因此,这意味着任务1和任务2可以由不同的线程并行运行以提高应用程序的性能。因此,让我们将其分解为一个多线程应用程序,
线程1的职责是
- 与服务器进行一些连接
 - 等待线程2从XML加载数据
 - 对从XML加载的数据进行处理
 
线程2的职责是
- 从XML加载数据
 - 通知另一个线程,即等待消息
 
使用条件变量实现此目的的代码如下:
#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
using namespace std::placeholders;
class Application
{
	std::mutex m_mutex;
	std::condition_variable m_condVar;
	bool m_bDataLoaded;
public:
	Application()
	{
		m_bDataLoaded = false;
	}
	void loadData()
	{
		// Make This Thread sleep for 1 Second
		// 等待1秒
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
		std::cout << "Loading Data from XML" << std::endl;
		// Lock The Data structure
		// 锁定数据结构
		std::lock_guard<std::mutex> guard(m_mutex);
		// Set the flag to true, means data is loaded
		// 设定数据被加载
		m_bDataLoaded = true;
		// Notify the condition variable
		// 通知变量
		m_condVar.notify_one();
	}
	bool isDataLoaded()
	{
		return m_bDataLoaded;
	}
	void mainTask()
	{
		std::cout << "Do Some Handshaking" << std::endl;
		// Acquire the lock
		std::unique_lock<std::mutex> mlock(m_mutex);
		// Start waiting for the Condition Variable to get signaled
		// Wait() will internally release the lock and make the thread to block
		// As soon as condition variable get signaled, resume the thread and
		// again acquire the lock. Then check if condition is met or not
		// If condition is met then continue else again go in wait.
		// 开始等待条件变量收到信号,Wait()将在内部释放锁并使线程阻塞,一旦条件变量得到信号,就恢复线程并再次获得锁。
		//然后检查是否满足条件,如果条件满足,则继续,否则继续等待。
		m_condVar.wait(mlock, std::bind(&Application::isDataLoaded, this));
		std::cout << "Do Processing On loaded Data" << std::endl;
	}
};
int main()
{
	Application app;
	std::thread thread_1(&Application::mainTask, &app);
	std::thread thread_2(&Application::loadData, &app);
	thread_2.join();
	thread_1.join();
	return 0;
}
输出为:
Do Some Handshaking
Loading Data from XML
Do Processing On loaded Data
7.4 参考
https://thispointer.com//c11-multithreading-part-7-condition-variables-explained/
[编程基础] C++多线程入门7-条件变量介绍的更多相关文章
- [编程基础] C++多线程入门6-事件处理的需求
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 6 事件处 ...
 - [编程基础] C++多线程入门8-从线程返回值
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 8 从线程返回值 8 ...
 - [编程基础] C++多线程入门4-数据共享和资源竞争
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++ 11标准. 4 数据共享和资源 ...
 - [编程基础] C++多线程入门5-使用互斥锁解决资源竞争
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 5 使用互 ...
 - [编程基础] C++多线程入门3-小心地将参数传递给线程
		
原始C++标准仅支持单线程编程.新的C++标准(称为c++11或c++0x)于2011年发布.在c++11中,引入了新的线程库.因此运行本文程序需要C++至少符合c++11标准. 文章目录 3 小心地 ...
 - [编程基础] C++多线程入门1-创建线程的三种不同方式
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 1 创建线程的三种不 ...
 - [编程基础] C++多线程入门10-packaged_task示例
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 10 pa ...
 - [编程基础] C++多线程入门9-async教程和示例
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 9 asy ...
 - [编程基础] C++多线程入门2-连接和分离线程
		
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 2 连接和 ...
 
随机推荐
- C语言------循环结构II
			
仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2 .实训目的及要求 3 .源代码及运行截图 4 .小结 1 .实训名称 实训6: ...
 - Vue中router路由的使用、router-link的使用(在项目中的实际运用方式)
			
文章目录 1.先看router中的index.js文件 2.router-link的使用 3.实现的效果 前提:router已经安装 1.先看router中的index.js文件 import Vue ...
 - 齐博x1自定义字段关联其它字段的隐藏显示
			
如下图,对于单选\多选\下拉框这种表单类型, 选择某一项后, 你还想他关联其它选项的隐藏或显示,你可以加多一个参数设置处理通常情况,用得最普遍的,就是两项参数,用竖线隔开,比如下面的1|洋房2|别墅 ...
 - faker
			
faker是一个生成伪造数据的Python第三方库,可以伪造城市,姓名,文班等各自信息,而且支持中文 安装 pip3 install faker 使用 # 导包 from faker impo ...
 - Selenium4+Python3系列(六) - Selenium的三种等待,强制等待、隐式等待、显式等待
			
为什么要设置元素等待 直白点说,怕报错,哈哈哈! 肯定有人会说,这也有点太直白了吧. 用一句通俗易懂的话就是:等待元素已被加载完全之后,再去定位该元素,就不会出现定位失败的报错了. 如何避免元素未加载 ...
 - .net 温故知新:【8】.NET 中的配置从xml转向json
			
一.配置概述 在.net framework平台中我们常见的也是最熟悉的就是.config文件作为配置,控制台桌面程序是App.config,Web就是web.config,里面的配置格式为xml格式 ...
 - 2022HNCTF--WEB
			
@ 目录 [Week1]Interesting_http 分析 payload [Week1]2048 分析 payload [Week1]easy_html 分析 paylaod [Week1]In ...
 - Arch Linux + KDE 配置&美化(持续更新~)
			
Arch Linux + KDE 配置&美化(持续更新~) 这篇文章着重记录archlinux + KDE的一个基本的配置过程.不包括安装过程(使用archInstall.sh).内容大概有以 ...
 - Azure DevOps Server 设置项目管理用户,用户组
			
一,引言 Azure DevOps Server 搭建完成后,关于如何进行项目管理,项目成员管理等,我们接着上一篇文章,继续讲解 Azure DevOps Server 的用户,用户组.首先,我们需要 ...
 - ui自动化测试数据复原遇到的坑——2、python连接informix时pytest报致命错误Windows fatal exception: access violation
			
python连接informix只能通过jdbc(需要先部署java环境.我试过到IBM上下载ODBC但结局是失败的),在执行pytest时发现有一串报错(大致是下面的这样): Windows fat ...