网站想自己做怎么弄/搜索引擎推广
文章目录
- 1. 等待事件或等待其他条件
- 1.1 凭借条件变量等待条件成立
- 1.1.1 std::condition_variable
- 1.1.2 std::condition_variable_any
- 1.1.3 std::condition_variable和std::condition_variable_any之间的区别
- 上个章节我们讨论了如何对共享数据的一个保护,通过std::lock_guard、std::unique_lock、初始化过程中使用std::call_once、std::once_flag、多个线程读取少量线程写入的时候使用std::shared_lock、std::unique_lock和std::shared_mutex或std::shared_timed_mutex搭配使用,还有单线程递归加锁的方式std::recursive_mutex的使用方法。
- 但是有时候我们不仅需要保护共享数据,还需要令独立线程上的行为同步。那么本章节我们就来讲一下线程同步的几种方法。
1. 等待事件或等待其他条件
有的时候需要各个线程之间协同操作,比如A线程需要等待B线程完成某一个功能之后才开始执行,那么有没有什么办法,B线程完成功能之后通知A线程一声,然后A线程接受到信号之后就开始工作呢?肯定是有的。
1.1 凭借条件变量等待条件成立
那么就开始介绍std::condition_variable 和 std::condition_variable_any的使用。
std::condition_variable 和 std::condition_variable_any 是 C++ 中用于多线程同步的两个类。它们都允许线程在等待某个条件变为真之前挂起自己,以免造成无谓的 CPU 时间浪费。
1.1.1 std::condition_variable
std::condition_variable 是 C++11 中引入的一个线程同步原语,用于在等待某个条件变为真之前挂起当前线程。使用 std::condition_variable 时,通常需要先定义一个 std::mutex,因为std::condition_variable仅限于与std::mutex一起使用,然后用 std::unique_lockstd::mutex 对其进行上锁,最后通过 std::condition_variable::wait() 解锁并且挂起当前线程:
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker_thread() {// 等待条件变为真std::unique_lock<std::mutex> lck(mtx);while (!ready) {cv.wait(lck);}// 条件已经变为真,执行一些操作// ...if (lck.owns_lock()){std::cout << "lck has locked" << std::endl;}
}int main() {// 模拟某些操作std::this_thread::sleep_for(std::chrono::seconds(5));// 通知等待的线程条件已经变为真{std::lock_guard<std::mutex> lck(mtx);ready = true;}cv.notify_one();std::thread t(worker_thread);t.join();return 0;
}
在上面的代码中,worker_thread() 函数等待 ready 变为 true,如果当前 ready 的值为 false,则调用 cv.wait(lck) 挂起当前线程,同时释放 lck。当 cv.notify_one() 被调用时,cv.wait(lck) 会返回,worker_thread() 函数会重新获得 lck,然后执行一些操作。
需要注意的是,由于 std::condition_variable::wait() 可能会出现虚假唤醒(即没有被 notify 也会从 wait() 函数中返回),因此在使用 std::condition_variable 时,通常需要将等待条件的语句用循环包围起来,以确保条件变为真时不会错过信号。
当然也可以这样写:
#include <iostream>
#include <mutex>
#include <thread>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;void worker_thread() {// 等待条件变为真std::unique_lock<std::mutex> lck(mtx);cv.wait(lck, [&]() {return ready; }); // 条件已经变为真,执行一些操作// ...if (lck.owns_lock()){std::cout << "lck has locked" << std::endl;}
}int main() {// 模拟某些操作std::this_thread::sleep_for(std::chrono::seconds(5));// 通知等待的线程条件已经变为真{std::lock_guard<std::mutex> lck(mtx);ready = true;}cv.notify_one();std::thread t(worker_thread);t.join();return 0;
}
在段代码里面使用了cv.wait(lock, [&]() { return ready; })进行等待条件成立。正好在此介绍一下std::condition_variable::wait()函数的用法:
std::condition_variable::wait()是一个用于等待通知的函数,其使用方式如下:
template< class Predicate > void wait(std::unique_lock<std::mutex>& lock, Predicate pred );
其中,lock是一个已经加锁的互斥量(必须是 std::unique_lock 类型),pred是一个可调用对象,用于判断等待条件是否满足。函数执行时会自动释放锁,并阻塞当前线程直到被通知。当线程被通知后,函数会重新获得锁,并重新检查等待条件。如果等待条件满足,函数返回;否则,函数再次进入阻塞状态等待下一次通知。
1.1.2 std::condition_variable_any
std::condition_variable_any 是 C++11 中引入的另一个线程同步原语,它的作用与 std::condition_variable 相同,但是可以与任何可锁定的互斥量(std::mutex、std::shared_mutex、std::recursive_mutex)等等一起使用。使用 std::condition_variable_any 时,需要先定义一个互斥量,然后使用 std::unique_lock 对其进行上锁。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex mtx;
std::condition_variable_any cv;
bool ready = false;void worker_thread() {// 等待条件变为真{std::unique_lock<std::mutex> lck(mtx);while (!ready) {cv.wait(lck);}}// 条件已经变为真,执行一些操作// ...std::cout << "shared data" << std::endl;
}int main() {// 模拟某些操作std::this_thread::sleep_for(std::chrono::seconds(1));// 通知等待的线程条件已经变为真{std::lock_guard<std::mutex> lck(mtx);ready = true;}cv.notify_one();std::thread t(worker_thread);t.join();return 0;
}
注意:至于为什么能在main函数中使用std::lock_guard,而在worker_thread()函数中不能使用std::lock_guard,这是因为std::condition_variable或者std::condition_variable_any在等待操作的过程中要释放互斥量,如果使用 std::lock_guard,那么在等待操作期间就无法释放互斥量,从而无法满足 std::condition_variable 的要求。
std::unique_lock 比 std::lock_guard 更灵活,因为它允许在构造时不锁定互斥量,在析构时再解锁。这使得 std::unique_lock 可以用于实现一些更为复杂的同步操作,例如超时等待、可重入锁等。此外,std::unique_lock 还提供了一些额外的功能,例如手动锁定和解锁互斥量、转移互斥量的所有权等。
在使用 std::condition_variable或者std::condition_variable_any时,我们通常需要使用 std::unique_lock 来锁定互斥量,并在等待操作期间释放互斥量。这样可以让其他线程获得互斥量并修改共享变量,从而避免死锁的情况。
1.1.3 std::condition_variable和std::condition_variable_any之间的区别
std::condition_variable 和 std::condition_variable_any 都是用于多线程同步的 C++ 标准库类,它们的主要区别在于:
- 适用范围:
std::condition_variable 只能与 std::unique_lockstd::mutex 配合使用,而 std::condition_variable_any 可以与任何能够提供 lock() 和 unlock() 成员函数的互斥量配合使用,包括 std::mutex、std::recursive_mutex、std::shared_mutex 等等。 - 实现细节:
std::condition_variable_any 的实现可能比 std::condition_variable 更为复杂,因为它需要支持不同类型的互斥量,而且可能需要在等待队列中存储更多的信息来避免死锁和无效的等待。
综上所述,std::condition_variable 更为简单且更为常用,适用于绝大多数的同步场景。而 std::condition_variable_any 则更加灵活,适用于一些特殊的同步场景,例如需要使用不同类型的互斥量、需要跨线程进行等待和通知等。
相关文章:

C++并发之探索编程三
文章目录1. 等待事件或等待其他条件1.1 凭借条件变量等待条件成立1.1.1 std::condition_variable1.1.2 std::condition_variable_any1.1.3 std::condition_variable和std::condition_variable_any之间的区别上个章节我们讨论了如何对共享数据的一个保护,通过std::lo…...

某智能驾驶企业:CACTER云网关为O365系统护航
01 客户背景 某智能驾驶企业是一家国际性的高科技创新型企业,在智能驾驶领域处于全球领先地位,专注于为广大客户提供个性化的智能驾驶解决方案,共建美好智能新时代。 使用产品:CACTER邮件安全云网关 02 痛点难点问题 根据Corema…...

网络安全与信息安全的主要区别讲解-行云管家
生活中工作中,我们经常可以听到信息安全与网络安全这两个词语,但很多小伙伴对于两者区分不清楚,今天我们小编就给大家来简单讲解一下这两者的主要区别吧! 网络安全与信息安全的主要区别讲解 1、定义不同 网络安全是指网络系统的…...

Zabbix6.2利用模板和自定义监控项监控华为AR3260路由器
1:登录路由器的WEB管理控制台。在系统管理中找到SNMP然后开启SNMP代理,SNMP的版本可以只选择v2c都选择也无所谓,然后点击新建一个团体。 2:团体名称输入默认的public即可,在WEB端显示的是乱码,但是不影响使…...

MySQL Connector/C++使用过程中的问题
Linux环境下,使用mysql connector cpp的时候,链接的时候报错: /usr/bin/ld: warning: libssl.so.10, needed by /usr/lib64/libssh2.so.1, may conflict with libssl.so.1.1 /usr/bin/ld: ext/openssl/.libs/xp_ssl.o: undefined reference …...

SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法(内含源代码)
SpringBoot下的Spring——DAY04——动态代理总结、AOP、自定义注解进行拦截、动态获取注解参数、通知方法(内含源代码) 源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87549575 目录SpringBoot下的Spring——DAY0…...

Spark MLlib概述
Spark MLlib概述机器学习房价预测模型选型数据探索数据提取准备训练样本模型训练模型效果评估机器学习 机器学习的过程 : 基于历史数据,机器会根据一定的算法,尝试从历史数据中挖掘并捕捉出一般规律再把找到的规律应用到新产生的数据中,从而…...

Git 命令行5步解决冲突方法(亲测有效)
总体步骤如下: git pull --rebase 解决冲突文件 file1.c。git add file1.cgit commit -m "*****" git pushgit rebase --continue ,此时冲突消失强推,git push origin xxxx -f 本人解决的例子如下: 第一步、拉取…...

在线帮助文档——让用户更方便地获取帮助
在当今互联网时代,人们在使用各种产品或服务时,难免会遇到问题或疑问,需要寻求帮助。而在线帮助文档则成为了一种方便、快捷、高效的解决问题的方式。Baklib作为一款优雅的云知识库构建平台,可以帮助公司在线制作各种类型的帮助文…...

一小时轻松掌握Git,看这一篇就足够
文章目录序言:版本控制分类一、Git环境配置下载卸载安装二、常用linux命令三、基本配置四、Git基本操作0.原理图1.项目创建及克隆方式一:本地仓库搭建方式二:克隆远程仓库2.文件操作3.配置ssh公钥4.分支5.push代码参考序言:版本控…...

spring cloud stream 自定义binder
背景xxx,关键字 binder stream ,解决多中间件通信及切换问题直接主菜:spring cloud stream 架构中间件 --- binder --- channel --- sink --- (处理)---source ---channel ---binder ---中间件 springcloudstream已自己集成了kafk…...

计算机网络之HTTP协议
目录 一、HTTP的含义 1.1 理解超文本 1.2 理解应用层协议 1.3 理解HTTP协议的工作过程 二、HTTP协议格式 2.1 抓包工具的使用 2.2 理解协议格式 2.2.1 请求协议格式 2.2.2. 响应格式请求 一、HTTP的含义 HTTP(全称为“超文本传输协议”)&#x…...

如何挖掘专利创新点?
“无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里可以跳转到教程。” 对于广大的软件工程师来说…...

虚函数和纯虚函数
多态(polymorphism)是面向对象编程语言的一大特点,而虚函数是实现多态的机制。其核心理念就是通过基类访问派生类定义的函数。多态性使得程序调用的函数是在运行时动态确定的,而不是在编译时静态确定的。使用一个基类类型的指针或…...

Framework源码面试——Handler与事件传递机制面试集合
Handler面试题 Handler的作用: 当我们需要在子线程处理耗时的操作(例如访问网络,数据库的操作),而当耗时的操作完成后,需要更新UI,这就需要使用Handler来处理,因为子线程不能做更新…...

iOS开发-bugly符号表自动上传发布自动化shell
这里介绍的是通过build得到的app文件和dSYM文件来打包分发和符号表上传。 通过Archive方式打包和获得符号表的方式以后再说。 一:bugly工具jar包准备 bugly符号表工具下载地址:(下载完成后放入项目目录下,如不想加入git可通过gitIgnore忽略…...

MySQL OCP888题解046-哪些语句会被记录到binlog
文章目录1、原题1.1、英文原题1.2、中文翻译1.3、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3.1、知识点1:binlog_format选项3.2、知识点2:Performance Schema(性能模式)4、总结1、原题 1.1、英文原题 You enable binary logging on MySQL S…...

【前端学习】D5:CSS进阶
文章目录前言系列文章目录1 精灵图Sprites1.1 为什么需要精灵图?1.2 精灵图的使用2 字体图标iconfont2.1 字体图标的产生2.2 字体图标的优点2.3 字体文件格式2.4 字体图标的使用2.5 字体图标的引入2.6 字体图标的追加3 CSS三角3.1 普通三角3.2 案例4 CSS用户界面样式…...

【bioinfo】融合检测软件FusionMap分析流程和报告结果
文章目录写在前面FusionMap融合检测原理FusionMap与其他软比较FusionMap分析流程FusionMap结果文件说明FusionMap mono CUP设置图片来源: https://en.wikipedia.org/wiki/Fusion_gene写在前面 下面主要内容是关于RNA-seq数据分析融合,用到软件是FusionMap 【Fusion…...

C++基础了解-17-C++日期 时间
C日期 & 时间 一、C日期 & 时间 C 标准库没有提供所谓的日期类型。C 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C 程序中引用 头文件。 有四个与时间相关的类型:clock_t、time_t、size_t 和 …...

MOV压敏电阻的几种电路元件功能及不同优势讲解
压敏电阻,通常是电路为防护浪涌冲击电压而使用的一种电子元器件,相比其他的浪涌保护器来说,也有那么几个不一样的优势,那么,具体有哪些?以及关于它的作用,你都知道吗?以下优恩小编为…...

uniapp+uniCloud实战项目报修小程序开发
前言 本项目基于 uniapp uniCloud 云开发,简单易用,逻辑主要是云数据库的增删查改,页面大部分自写,部分使用uniUI, uView 组件库。大家可用于学习或者二次开发,有什么不懂的地方可联系 wechat:MrYe443。用…...

演唱会的火车票没了?Python实现12306查票以及zidong购票....
嗨害大家好!我是小熊猫~ 不知道大家抢到演唱会的门票没有呢? 不管抢到没有,火车票也是很重要的哇 24小时抢票不间断的那种喔~ ~ ~ 不然可就要走路去了喔~ 准备工作 环境 Python 3.8Pycharm 插件 谷歌浏览器驱动 模块 需要安装的第三方模块&am…...

Linux发行版本与发行版的简单的介绍
Linux linux下有很多发行的版本,或者称之为魔改版本。以下介绍一些常见的版本,以避免名词的混淆。 linux是提供了一个内核,就像是谷歌的内核一样,QQ浏览器就是使用的谷歌的内核,也算是一个发行版本。 Ubuntu&#x…...

前后端分离项目学习-vue+springboot 博客
前后端分离项目 文章总体分为2大部分,Java后端接口和vue前端页面 项目演示:www.markerhub.com:8084/blogs Java后端接口开发 1、前言 从零开始搭建一个项目骨架,最好选择合适,熟悉的技术,并且在未来易拓展…...

关于指针运算的一道题
目录 刚看到这道题的时候我也和大多数小白一样感到无从下手,但是在我写这篇博客的前几分钟开始我对这道题有了一点点的理解。所以我就想着趁热打铁,写一篇博客来记录一下我的想法。 题目如下: 画图: 逐一解答: 题一…...

【论文简述】Learning Optical Flow with Kernel Patch Attention(CVPR 2022)
一、论文简述 1. 第一作者:Ao Luo 2. 发表年份:2022 3. 发表期刊:CVPR 4. 关键词:光流、局部注意力、空间关联、上下文关联 5. 探索动机:现有方法主要将光流估计视为特征匹配任务,即学习在特征空间中将…...

Java学习-MySQL-列的数据类型
Java学习-MySQL-列的数据类型 数值 tinyint - 1个字节smallint - 2个字节mediumint - 3个字节int - 4个字节bigint - 8个字节float - 4个字节double - 8个字节decimal - 字符串形式的浮点数 字符串 char - 0~255varchar - 可变字符串 0~65535tinytext - 微型文本 2^8-1text…...

终端配色-Docker容器终端
20230309 - 0. 引言 平时使用SSH,通常都是使用securecrt来用,毕竟也算是之前windows下一种使用的工具,在mac下使用还算方便;进入终端后,可以通过调整配色来调整编程环境。平时经常使用屎黄色的那种配色,毕…...

SQL基础培训04-插入数据
知识点: 假设有订单表 CREATE TABLE SEOrder ( FID int identity(...