【C++】条件变量condition_variable

文章目录

  • 1. 条件变量定义及特点
  • 2. 代码示例
  • 3. wait方法
  • 4. wait_for方法
  • 5. notify_all和notify_one
  • 6. 思考

1. 条件变量定义及特点

条件变量 用于在线程之间协调共享资源的访问。它允许一个线程等待特定条件的满足(如某个值的变化),而另一个线程在条件满足时通知(或唤醒)等待的线程。这种机制可以防止线程忙等待,从而提高系统效率。

条件变量特点:
1. 等待和通知机制:线程可以等待某个条件的改变,而不需要一直占用CPU
2. 与互斥锁配合使用, 以保护共享数据的访问
3. 线程通信:实现线程之间的高效通信

注意事项: 条件变量必须与互斥锁一起使用,以确保在检查条件(while(!ready))和修改共享数据(ready=true)时的线程安全,如果省略了互斥锁,可能导致数据竞争和其它并发问题

2. 代码示例

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>using namespace std;mutex mtx;		// 定义互斥锁
condition_variable cv; // 创建一个条件变量实例
bool flag = false;   // 全局变量flagvoid myPrint(int i){unique_lock<mutex> lck(mtx);// while (!flag){//     cv.wait(lck);  // 条件不成立 进入阻塞状态 释放CPU资源  释放掉锁 等待别人的唤醒// }cv.wait(lck, [](){return flag;}); // 这个写法与上面while效果相同cout<< this_thread::get_id() << "-" << i <<endl;
}void updateflag(){cout<< "this is update" <<endl;this_thread::sleep_for(3s);unique_lock<mutex> lck(mtx);flag = true;cv.notify_all();
}int main(int argc, char** argv){vector<thread> mybox;for(size_t i=0; i<10; i++){mybox.emplace_back(myPrint, i);}updateflag();for(thread& t: mybox){t.join();}return 0;
}

3. wait方法

wait方法相当于阻塞当前线程,直到另一个线程调用同一个 std:condition_variable 实例的notify_one 或 notify_all方法,或者直到指定的谓词函数(即条件)返回 true。如果你没有通知,即使条件为TRUE,它也不会被执行。如果,你通知了,但是条件不成立,它仍然被阻塞,不会执行。它的执行顺序是 先通知 再检测条件。

参数:
std::unique_lock <std:mutex> & lock:一个与互斥锁相关联的 std:unique_lock 对象。调用 wait 时,这个锁会被自动释放,允许其他线程获取该锁并执行。当 wait 返回时,锁会被重新获取。

工作原理:

  1. 释放锁:当线程调用 wait 方法时,它会首先释放与 std::unique_lock 关联的互斥锁。这是为了允许其他线程可以访问和修改与条件变量相关的共享数据。
  2. 进入等待队列:释放锁后,线程会进入条件变量的等待队列中,进入阻塞状态。此时线程不再消耗CPU时间,直到被唤醒。
  3. 等待条件或通知:线程在等待队列中等待,直到两个条件之一发生:

3.1 另一个线程调用了同一个条件变量的 notify_one 或 notify_all方法,并且该线程是等待队列中的第一个线程(对于notify_one)或等待队列中的所有线程(对于notify_all)
3.2 谓词函数 pred 返回 true

  1. 重新获取锁:当线程被唤醒后(无论是由于收到通知还是条件成立),它会尝试重新获取之前释放的互斥锁。如果此时锁已经被其他线程持有,则该线程会阻塞在互斥锁上,直到获得锁。
  2. 检查条件:获得锁后,线程会再次调用谓词函数 pred 来检查条件是否成立。如果条件不成立(即 pred 返回false),则线程会重新进入等待队列,并释放锁,继续等待。这个过程会不断重复,直到条件成立
  3. 继续执行:如果条件成立(即pred返回true),则线程会退出wait方法,并继续执行后续的代码

注意事项:

  1. wait方法必须在已经锁定互斥锁的情况下调用,否则会抛出std::system_error异常
  2. 在调用wait方法之前,应该确保与条件变量相关的共享数据已经被初始化,并且已经设置了适当的条件
  3. 由于wait方法会释放和重新获取锁,因此在使用wait方法时应该确保没有其它线程会在等待期间修改与条件变量相关的共享数据,以避免竞态条件

4. wait_for方法

  1. wait_for方法与wait方法类似,但它允许你指定一个超时时间。如果在这段时间内条件没有满足,并且没有收到唤醒信号,那么wait_for会返回,并且线程会重新获取互斥锁。
  2. wait_for方法接受一个时间间隔作为参数,表示线程愿意等待的最长时间。这个时间间隔可以是 std::chrono 库中定义的任何时间单位。
  3. wait_for的返回值是一个std::cv_statu枚举值,表示等待操作的结果可能的返回值包括:
    std::cv_status::no_timeout:表示等待操作成功完成,即在超时时间内条件被满足或收到了唤醒信号
    std::cv_status::timeout:表示等待操作因超时而结束,条件没有被满足且没有收到唤醒信号

5. notify_all和notify_one

notify_all()和 notify_one()是条件变量(std::condition_variable)的两个成员函数,用于唤醒等待条件变量的线程。
a. notify_all():
作用: 唤醒所有等待该条件变量的线程。
使用场景: 适用于多个线程需要同时检査条件的情况。通常用于广播通知,让所有等待的线程都重新检查条件。
b. notify_one():
作用: 唤醒一个等待该条件变量的线程。
使用场景: 适用于只有一个线程需要处理条件的情况。通常用于优先级调度或队列处理,让其中一个线程获得执行权

6. 思考

1. 如果调用notify_one()次数超过等待通知线程数会怎么样?

如果调用 notify_one() 的次数超过了等待的线程数,则多余的通知将没有效果。 notify_one() 只会唤醒当前在等待队列中的一个线程,并不会将通知累积。例如有 2 个线程在等待,但调用了 3 次 notify_one(),则只有 2 个线程会被唤醒,剩余的 1 次通知将被丢弃

2.如果使用notify_all()进行通知时,没有在等待的线程会怎样?

调用notify_all() 时,如果没有线程在 wait() 状态,那么通知将直接丢失

3.如果有多个线程在等待,notify_one()会通知哪个线程?

当有多个线程在等待同一个条件变量时,notify_one() 会随机唤醒其中一个线程,但具体唤醒哪一个线程由系统决定。一般来说,唤醒哪个线程取决于操作系统的调度策略和线程的等待顺序。C++ 标准并没有定义确切的唤醒顺序,因此它具有不确定性,可能因系统和实现的不同而有所变化。

本文参考:https://www.bilibili.com/video/BV1E4421D76e?spm_id_from=333.788.player.switch&vd_source=cf0b4c9c919d381324e8f3466e714d7a

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记

这是一篇港科大学生在google research 实习期间发在ECCV2024的语义引导生成式修复的文章&#xff0c;港科大陈启峰也挂了名字。从首页图看效果确实很惊艳&#xff0c;尤其是第三行能用文本调控修复结果牌上的字。不过看起来更倾向于生成&#xff0c;对原图内容并不是很复原&…

Dubbo负载均衡

负载均衡策略与配置细节 Dubbo 内置了 client-based 负载均衡机制&#xff0c;如下是当前支持的负载均衡算法&#xff0c;结合上文提到的自动服务发现机制&#xff0c;消费端会自动使用 Weighted Random LoadBalance 加权随机负载均衡策略 选址调用。 如果要调整负载均衡算法…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十二:在屏幕上显示多路视频播放,可以有不同的分辨率,格式和帧率。

上图是在安防领域的要求&#xff0c;一般都是一个屏幕上有显示多个摄像头捕捉到的画面&#xff0c;这一节&#xff0c;我们是从文件中读取多个文件&#xff0c;显示在屏幕上。 一 改动UI文件 这里我们要添加两个label&#xff0c;为了区分我们设置一下背景色&#xff08;这个是…

前言2、VS(Visual Studio)-2022使用

早前用VS-2010编译平台&#xff0c;进行C语言编程学习。 现如今&#xff0c;为了适应未来发展趋势以及日新月异的新功能&#xff0c;就此转到VS-2022编译平台&#xff1b; 由于都是VS编译平台&#xff0c;大多数基础功能都类似&#xff0c;关于一些基础操作可参考前言1&#…

深入了解逻辑回归:机器学习中的经典算法

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

[High Speed Serial ] Xilinx

Xilinx 高速串行数据接口 收发器产品涵盖了当今高速协议的方方面面。GTH 和 GTY 收发器提供要求苛刻的光互连所需的低抖动&#xff0c;并具有世界一流的自适应均衡功能&#xff0c;具有困难的背板操作所需的 PCS 功能。 Versal™ GTY &#xff08;32.75Gb/s&#xff09;&…

基于CNN-RNN的影像报告生成

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【PaddleNLP的FAQ问答机器人】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

java list使用基本操作

import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;public class Main {public static void main(String[] args) {ArrayList list new ArrayList();list.add("张三");list.add("李四");list.add("王五");l…

高级 <HarmonyOS主题课>借助AR引擎帮助应用实现虚拟与现实交互的能力的课后习题

持而盈之&#xff0c;不如其已&#xff1b; 揣而锐之&#xff0c;不可长保。 金玉满堂&#xff0c;莫之能守&#xff1b; 富贵而骄&#xff0c;自遗其咎。 功成身退&#xff0c;天之道也。 VR (Virtual Reality): 虚拟现实技术 AR (Augmented Reality): 增强现实) XR.(Extend…

高校实验室安全巡检系统设计与实现(源码+定制+开发)高校实验室巡检系统、实验室安全管理平台、实验室安全监控系统、智能实验室巡查系统、高校实验室风险管理

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

102、Python并发编程:Queue与生产者消费者模型实现解耦、协作

引言 在实际业务场景中&#xff0c;很多时候在处理复杂任务的时候&#xff0c;会拆分上下游各个环节&#xff0c;形成一个类似于流水线的处理方式。上游类似于生产者&#xff0c;下游要依赖上游的输出进行工作&#xff0c;类似于消费者。但是&#xff0c;很多时候&#xff0c;…

【梯度提升专题】XGBoost、Adaboost、CatBoost预测合集:抗乳腺癌药物优化、信贷风控、比特币应用|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p38115 分析师:Yang Yang&#xff0c;Kechen Zhao 在当今科技日新月异的时代&#xff0c;数据的有效利用成为各领域突破发展的关键。于医疗领域&#xff0c;乳腺癌的高发性与严重性不容忽视&#xff0c;优化抗乳腺癌候选药物的筛选与特…

机器学习与AI|如何利用数据科学优化库存周转率?

对于所有零售商来说&#xff0c;良好的库存管理都是非常重要的。众所周知&#xff0c;商品如果不放在货架上就无法出售&#xff0c;而如果库存过多则意味着严重的财务负担。 但是做好库存管理绝非易事&#xff0c;它依赖于对未来需求的准确预测和确保始终有合适库存的敏捷供应链…

安卓智能对讲终端|北斗有源终端|三防对讲机|单兵终端|单北斗

在当今快速发展的通信技术时代&#xff0c;智能对讲手持机已成为众多行业领域中不可或缺的通讯工具。QM240T安卓智能对讲手持机&#xff0c;作为一款集先进技术与实用功能于一身的高端设备&#xff0c;凭借其卓越的性能和多样化的应用特性&#xff0c;正逐步引领对讲机市场的革…

【数据集】【YOLO】【目标检测】抽烟识别数据集 6953 张,YOLO/VOC格式标注,吸烟检测!

数据集介绍 【数据集】抽烟识别数据集 6953 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。数据集中包含1种分类&#xff1a;“smoking”。数据集来自国内外图片网站和视频截图。检测范围园区吸烟检测、禁烟区吸烟检测、监控吸烟检测、无人机吸烟检测等。 主页私…

软件设计师-上午题-15 计算机网络(5分)

计算机网络题号一般为66-70题&#xff0c;分值一般为5分。 目录 1 网络设备 1.1 真题 2 协议簇 2.1 真题 3 TCP和UDP 3.1 真题 4 SMTP和POP3 4.1 真题 5 ARP 5.1 真题 6 DHCP 6.1 真题 7 URL 7.1 真题 8 浏览器 8.1 真题 9 IP地址和子网掩码 9.1 真题 10 I…

视频制作与剪辑怎么学,零基础入门视频剪辑和制作

视频制作与剪辑是一门充满创意与挑战的艺术形式&#xff0c;对于零基础的学习者来说&#xff0c;没选对软件不了解剪辑步骤&#xff0c;入门可能会显得有些棘手。接下来&#xff0c;我们将一同探讨如何开启视频剪辑与制作之旅&#xff0c;让新手从零基础入门&#xff0c;逐步迈…

[Element] el-table修改滚动条上部分的背景色

[Element] el-table修改滚动条上部分的背景色 ::v-deep .el-table__cell .gutter {background: red;}

SAP ABAP开发学习——WDA 七 使用文本与消息

目录 从数据字典读取文本 使用OTR文本 从程序中调用OTR文本 消息分类 定义消息显示位置 text类消息的使用 T100 消息的使用 OTR消息实例 消息内容修改 从数据字典读取文本 使用OTR文本 可以自己创建OTR文本 从程序中调用OTR文本 消息分类 定义消息显示位置 text类消息的…

基于物联网设计的地下煤矿安全监测与预警

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发 1.5 模块的技术详情介绍【1】NBIOT-BC26模块【2】MQ5传感器【4】DHT11传感器【5】红外热释电人体检…