[编程基础] 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 连接和 ...
随机推荐
- 谣言检测(ClaHi-GAT)《Rumor Detection on Twitter with Claim-Guided Hierarchical Graph Attention Networks》
论文信息 论文标题:Rumor Detection on Twitter with Claim-Guided Hierarchical Graph Attention Networks论文作者:Erx ...
- 没有使用IaC的DevOps系统都是耍流氓
作为现代软件工程的基础实践,基础设施即代码(Infrastructure as Code, IaC)是云原生.容器.微服务以及DevOps背后的底层逻辑.应该说,以上所有这些技术或者实践都是以基础设施 ...
- C#中ref和out关键字的应用以及区别
首先:两者都是按地址传递的,使用后都将改变原来参数的数值. 其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所 ...
- Filter 筛选器(二)之 ExceptionFilter
public class MyExceptionFilter : IAsyncExceptionFilter { private readonly ILogger<MyExceptionFilt ...
- IDEAidea导入Scala包
IDEAidea导入Scala包 一.配置windows的scala的环境变量 二.IDEA导入scala插件 1.如图步骤导入IDEA的scala插件 三.添加本地的scala目录 这时候我们应该在 ...
- 云的安全组和网络ACL
云的安全组和网络ACL 1.流量控制: 安全组是云服务器.数据库等实例级别的流量控制 ACL是子网级别的流量控制 2.规则: 安全组和网络ACL都支持允许规则和拒绝规则 3.状态: 安全组有状态( ...
- Typora设置代码块Mac风格三个圆点
写作不停,美化不止! mac小圆点效果 原本代码块样式就挺....干净的,光秃秃的,太单调了: 是吧很丑,于是自己发挥改成了这样: 好吧还是太单调,也没好看到哪里去,于是隔了两天又重新改,DuangD ...
- 【日志系统】Loki日志监控 - 入门初体验
使用Grafana+Loki+Promtail入门级部署分布式日志系统(windows环境) 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放 ...
- ES6 学习笔记(十二)代理器Proxy的简单使用
1.前言 以前在学习react时做了个仿手机端的QQ音乐项目.当时的数据是通过proxy代理的QQ音乐数据接口,直接写在package.json里面.Proxy 对象(Proxy)是 ES6的特性,只 ...
- Oracle部署,关于日志文件系统选择(硬盘格式化、挂载)
之前部署过好多Oracle服务,采用的日志文件系统一直是ext3.但是我观察到很多人在格式化/挂载数据盘时,采用的日志文件系统类型有ext3.ext4.xfs等,这不禁让我发出疑问,哪个类型的数据处理 ...