当前位置: 首页 > news >正文

[C++11]_[初级]_[工作线程如何监听主线程条件变量wait_for方法的使用]

场景

  1. 在开发多线程程序时,有时候需要启动一个线程来监听外部进程的执行情况,并且在指定时间如果还没运行结束就强制结束外部线程。那么C++标准库有这种监听线程并能在超时时提示的方法吗?

说明

  1. C++11<condition_variable>里就可以用条件变量来等待信号通知, 并设置超时时间。 超时时间的含义是,wait_for在超时达到时会自动唤醒mutex并不断尝试获取锁,当锁被获取时,进入下一条代码。
template< class Lock, class Rep, class Period >std::cv_status wait_for( Lock& lock,const std::chrono::duration<Rep, Period>& rel_time );
mutex.lock();
cond.wait_for(mutex, std::chrono::seconds(10));
mutex.unlock();
  1. wait_for的重载函数还有一个返回值是bool的函数对象。这个函数对象是为了避免虚假的唤醒,比如被错误的notify_one唤醒时,需要判断是否返回true, 如果返回true, 那么结束等待,否则继续等到到超时。 这个带Predicate参数的实现等同于
    wait_until(lock, std::chrono::steady_clock::now() + rel_time, std::move(pred));.[1]
template< class Lock, class Rep, class Period, class Predicate >bool wait_for( Lock& lock, const std::chrono::duration<Rep, Period>& rel_time,Predicate pred );
  1. 以上的Predicate函数对象的作用等同于以下的实现:[2].
  • 进入等待前先判断Predicate是否为true, 如果为false,进度等待。
  • 如果等到超时,直接返回Predicate的值,即执行下一行代码。
  • 如果非超时的唤醒,那么返回第一步。
while (!pred())if (wait_until(lock, abs_time) == std::cv_status::timeout)return pred();
return true;.
  1. 注意,使用条件变量唤醒时,不需要加锁。cond1.notify_one(); [3]因为如果对通知操作进行加锁,那么通知发生时,等待线程唤醒后会尝试获取锁,但是获取不到会迅速阻塞,因为被通知的线程需要等待通知线程解锁。
The notifying thread does not need to hold the lock on the same mutex as the one held by the waiting thread(s); 
in fact doing so is a pessimization, since the notified thread would immediately block again, 
waiting for the notifying thread to release the lock. 
However, some implementations (in particular many implementations of pthreads) recognize this situation and 
avoid this "hurry up and 
wait" scenario by transferring the waiting thread from the condition variable's queue directly to the queue of the mutex within the notify call, without waking it up. 

例子

// test-wait-for.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <condition_variable>
#include <thread>
#include <mutex>
#include <chrono>using namespace std;void work_1(condition_variable_any& cond,mutex& mutex)
{mutex.lock();cond.wait_for(mutex, std::chrono::seconds(10));mutex.unlock();
}void TestWaitFor_1()
{condition_variable_any cond1;mutex mutex1;auto beg =  std::chrono::system_clock::now();thread t1(work_1,std::ref(cond1),std::ref(mutex1));std::this_thread::sleep_for(std::chrono::seconds(3));//cond1.notify_one();t1.join();std::chrono::duration<double> seconds = std::chrono::system_clock::now() - beg;printf("TestWaitFor_2 elapsed_seconds: %fs\n", seconds);
}void work_2(condition_variable_any& cond,mutex& mutex,bool& bFinish)
{mutex.lock();cond.wait_for(mutex, std::chrono::seconds(10), [&bFinish]{return bFinish; });mutex.unlock();
}void TestWaitFor_2(bool bValue)
{condition_variable_any cond1;mutex mutex1;bool bFinish = false;auto beg =  std::chrono::system_clock::now();thread t1(work_2,std::ref(cond1),std::ref(mutex1),std::ref(bFinish));std::this_thread::sleep_for(std::chrono::seconds(3));// 用来处理虚假的唤醒,即如果没有到timeout就收到唤醒且bFinish还为false的话,wait会继续。bFinish = bValue; // 想让notify_one的唤醒生效,必须bFinish = true;cond1.notify_one();t1.join();std::chrono::duration<double> seconds = std::chrono::system_clock::now() - beg;printf("TestWaitFor_2 elapsed_seconds: %fs\n", seconds);
}int main()
{std::cout << "Hello World!\n";std::cout << "\n==== TestWaitFor_1 ====" << endl;TestWaitFor_1();std::cout << "\n=== TestWaitFor_2 ==== bFinish = false" << endl;TestWaitFor_2(false);std::cout << "\n=== TestWaitFor_2 ==== bFinish = true" << endl;TestWaitFor_2(true);
}

输出

Hello World!==== TestWaitFor_1 ====
TestWaitFor_2 elapsed_seconds: 10.012182s=== TestWaitFor_2 ==== bFinish = false
TestWaitFor_2 elapsed_seconds: 10.008821s=== TestWaitFor_2 ==== bFinish = true
TestWaitFor_2 elapsed_seconds: 3.030650s

参考

  1. wait_for

  2. wait_util

  3. notify_one

  4. pthread_cond_signal

相关文章:

[C++11]_[初级]_[工作线程如何监听主线程条件变量wait_for方法的使用]

场景 在开发多线程程序时&#xff0c;有时候需要启动一个线程来监听外部进程的执行情况&#xff0c;并且在指定时间如果还没运行结束就强制结束外部线程。那么C标准库有这种监听线程并能在超时时提示的方法吗&#xff1f; 说明 在C11的<condition_variable>里就可以用…...

Openstack持久存储-Swift,Cinder,Manila三者之间的区别

总结不易&#xff0c;给个三连吧&#xff01;&#xff01;&#xff01; 补充&#xff1a; 文件共享存储服务Manila 在OpenStack生态系统中&#xff0c;Cinder和Manila分别提供了两种不同类型的存储服务&#xff0c;类似于传统的SAN&#xff08;存储区域网络&#xff09;和NAS&…...

深度学习第三弹:python入门与线性表示代码

一、python入门 1.熟悉基础数据结构——整型数据&#xff0c;浮点型数据&#xff0c;列表&#xff0c;字典&#xff0c;字符串&#xff1b;了解列表及字典的切片&#xff0c;插入&#xff0c;删除操作。 list1 [1, 2, 3, 4, 5] for each in list1:print(each) print(list1[1…...

解决报错记录:TypeError: vars() argument must have __dict__ attribute

解决报错记录&#xff1a;manager_pyplot_show vars(manager_class).get(“pyplot_show“) TypeError: vars() argument must 1.问题引申 在pycharm中调用matplotlib函数批量绘制维度图时&#xff0c;抛出异常&#xff1a; manager_pyplot_show vars(manager_class).get(&…...

SpringBoot 原理篇(day14)

配置优先级 SpringBoot 中支持三种格式的配置文件&#xff1a; 配置文件优先级排名&#xff08;从高到低&#xff09;&#xff1a; properties 配置文件yml 配置文件yaml 配置文件 注意事项 虽然 springboot 支持多种格式配置文件&#xff0c;但是在项目开发时&#xff0c;推荐…...

Vscode辅助编码AI神器continue插件

案例效果 1、安装或者更新vscode 有些版本的vscode不支持continue,最好更新到最新版,也可以直接官网下载 https://code.visualstudio.com/Download 2、安装continue插件 搜索continue,还未安装的,右下脚有个Install,点击安装即可 <...

Type-C单口便携显示器-LDR6021

Type-C单口便携显示器是一种新兴的显示设备&#xff0c;它凭借其便携性、高性能和广泛的应用场景等优势&#xff0c;正在成为市场的新宠。以下是Type-C单口便携显示器的具体运用方式&#xff1a; 一、连接与传输 1. **设备连接**&#xff1a;Type-C单口便携显示器通过Type-C接…...

青少年编程与数学 02-006 前端开发框架VUE 19课题、内置组件

青少年编程与数学 02-006 前端开发框架VUE 19课题、内置组件 一、Transition<Transition> 组件基于 CSS 的过渡效果CSS 过渡 class为过渡效果命名CSS 的 transitionCSS 的 animation自定义过渡 class同时使用 transition 和 animation深层级过渡与显式过渡时长性能考量 J…...

腾讯云AI代码助手编程挑战赛 - 使用 JavaScript 构建一个简易日历

功能简介&#xff1a; 动态年份选择&#xff1a;用户可以通过下拉框选择从 2000 年到 2050 年的任意年份。全年日历生成&#xff1a;根据用户选择的年份&#xff0c;动态生成该年份的所有 12 个月份的日历。直观的 UI 设计&#xff1a;使用 CSS 美化日历外观&#xff0c;使日历…...

Xcode 正则表达式实现查找替换

在软件开发过程中&#xff0c;查找和替换文本是一项常见的任务。正则表达式&#xff08;Regular Expressions&#xff09;是一种强大的工具&#xff0c;可以帮助我们在复杂的文本中进行精确的匹配和替换。Xcode 作为一款流行的开发工具&#xff0c;提供了对正则表达式的支持。本…...

学习flv.js

前言 flv.js一款使用纯 JavaScript 编写的 HTML5 Flash 视频 (FLV) 播放器&#xff0c;无需 Flash&#xff01;&#xff01;&#xff01;flv.js 的工作原理是将 FLV 文件流转换为 ISO BMFF&#xff08;碎片 MP4&#xff09;片段&#xff0c;然后通过Media Source Extensions&l…...

FreePBX 17 on ubuntu24 with Asterisk 20

版本配置&#xff1a; FreePBX 17&#xff08;最新&#xff09; Asterisk 20&#xff08;最新Asterisk 22&#xff0c;但是FreePBX 17最新只支持Asterisk 21&#xff0c;但是21非LTS版本&#xff0c;所以选择Asterisk 20&#xff09; PHP 8.2 Maria DB (v10.11) Node J…...

【算法】算法大纲

这篇文章介绍计算机算法的各个思维模式。 包括 计数原理、数组、树型结构、链表递归栈、查找排序、管窥算法、图论、贪心法和动态规划、以及概率论:概率分治和机器学习。没有办法逐个说明,算法本身错综复杂,不同的算法对应着不同的实用场景,也需要根据具体情况设计与调整。…...

【MySQL】SQL菜鸟教程(一)

1.常见命令 1.1 总览 命令作用SELECT从数据库中提取数据UPDATE更新数据库中的数据DELETE从数据库中删除数据INSERT INTO向数据库中插入新数据CREATE DATABASE创建新数据库ALTER DATABASE修改数据库CREATE TABLE创建新表ALTER TABLE变更数据表DROP TABLE删除表CREATE INDEX创建…...

安装本地测试安装apache-doris

一、安装前规划 我的服务器是三台麒麟服务器,2台跑不起来,这是我本地的,内存分配的也不多。 fe192.168.1.13 主数据库端口9030访问 8Gbe192.168.1.13内存4G 硬盘50be192.168.1.14内存4G 硬盘50be192.168.1.12内存4G 硬盘5013同时安装的fe和be 。 原理:192.168.1.13 服…...

【Apache Paimon】-- 13 -- 利用 paimon-flink-action 同步 mysql 表数据

利用 Paimon Schema Evolution 核心特性同步变更的 mysql 表结构和数据 1、背景信息 在Paimon 诞生以前,若 mysql/pg 等数据源的表结构发生变化时,我们有几种处理方式 (1)人工通知(比如常规的使用邮件),然后运维人员手动同步到数据仓库中 (2)使用 flink 消费 DDL bi…...

IOS HTTPS代理抓包工具使用教程

打开抓包软件 在设备列表中选择要抓包的 设备&#xff0c;然后选择功能区域中的 HTTPS代理抓包。根据弹出的提示按照配置文件和设置手机代理。如果是本机则会自动配置&#xff0c;只需要按照提醒操作即可。 iOS 抓包准备 通过 USB 将 iOS 设备连接到电脑&#xff0c;设备需解…...

在 Ubuntu 22.04 上从 Wayland 切换到 X11的详细步骤

在 Ubuntu 22.04 上从 Wayland 切换到 X11&#xff0c;步骤其实很简单&#xff0c;主要是在登录界面进行选择。以下是详细的步骤&#xff1a; 步骤 1&#xff1a;退出当前会话 首先&#xff0c;点击屏幕右上角的用户菜单&#xff0c;选择 注销 或 退出&#xff0c;以退出当前…...

【Linux】4.Linux常见指令以及权限理解(2)

文章目录 3. Linux指令3.1 ls指令和rm指令补充3.2 man指令&#xff08;重要&#xff09;3.3cp指令&#xff08;重要&#xff09;输出重定向3.3.1ubuntu20.04如何安装tree 3.4 mv指令&#xff08;重要&#xff09;mv指令更改文件名mv指令更改目录名 如何看待指令指令的重命名3.5…...

ffmpeg aac s16 encode_audio.c

用ffmpeg库时&#xff0c;用代码对pcm内容采用aac编码进行压缩&#xff0c;出现如下错误。 [aac 000002bc5edc6e40] Format aac detected only with low score of 1, misdetection possible! [aac 000002bc5edc8140] Error decoding AAC frame header. [aac 000002bc5edc81…...

从“单点防御”到“全局联动”:手把手教你用EDR和NDR构建企业安全闭环

从“单点防御”到“全局联动”&#xff1a;手把手教你用EDR和NDR构建企业安全闭环 当企业的安全团队还在疲于应对零散的端点告警和网络流量异常时&#xff0c;攻击者早已开始采用自动化工具进行横向移动。传统孤立的防御手段就像用多个单点摄像头监控银行金库——每个摄像头都…...

手把手教你用JavaScript实现国密SM4加密(附Node.js与微信小程序兼容代码)

从零构建JavaScript国密SM4加密引擎&#xff1a;跨平台实战指南 国密SM4算法作为我国商用密码体系的核心标准&#xff0c;正在金融、政务等领域加速替代国际加密算法。但对于JavaScript开发者而言&#xff0c;直接可用的SM4实现往往面临三大痛点&#xff1a;Node.js与微信小程序…...

摒弃固定显示界面,程序根据使用场景,自动切换显示界面(简洁版/详细版),适配不同需求。

一、 实际应用场景描述 (Scenario)假设你正在开发一台高精度光谱分析仪。这台设备有三种典型的使用者&#xff1a;1. 研发工程师&#xff08;R&D&#xff09;&#xff1a;在实验室调试光路和算法。他们需要看到原始 ADC 值、温度漂移曲线、信噪比等详细数据。2. 质检员&…...

解码器精准调优:LoRA赋能Depth-Anything-V2实现绝对深度估计

1. LoRA技术如何革新Depth-Anything-V2的深度估计 当我在实验室第一次尝试用LoRA微调Depth-Anything-V2时&#xff0c;意外发现只需要调整解码器中1x1卷积层的极少量参数&#xff0c;就能让相对深度模型输出精确的绝对深度值。这就像给一个只会判断"远近"的模型突然装…...

2016-2025年地级市链长制数据

在产业链现代化与协同治理进程中&#xff0c;“链长制”作为一项关键的制度创新&#xff0c;为破解产业链条松散、协同不足等问题提供了重要抓手&#xff0c;其政策效果与影响机制成为当前学术研究与政策制定的焦点议题。周钰丁、田思远在研究中指出&#xff0c;产业链“链长制…...

迈瑞医疗营收超330亿,国际业务持续发力未来何在?

最近的财报季&#xff0c;各家上市公司的财报都牵动着每个人的心&#xff0c;就在最近迈瑞医疗的成绩单公布&#xff0c;营收超330亿&#xff0c;国际业务持续向好&#xff0c;这样的成绩单我们到底该怎么看待呢&#xff1f;一、迈瑞医疗业绩稳健向好据每日经济新闻的报道&…...

Marp CLI元数据管理:如何优化SEO和社交媒体分享

Marp CLI元数据管理&#xff1a;如何优化SEO和社交媒体分享 【免费下载链接】marp-cli A CLI interface for Marp and Marpit based converters 项目地址: https://gitcode.com/gh_mirrors/ma/marp-cli Marp CLI是一款强大的命令行工具&#xff0c;让你仅用纯Markdown就…...

Ubuntu系统资源监控实战:从命令行到图形化工具全解析

1. 为什么需要监控Ubuntu系统资源&#xff1f; 刚装好的Ubuntu系统跑得飞快&#xff0c;用着用着突然发现电脑变卡了&#xff1f;浏览器开多几个标签页就开始转圈&#xff1f;这种情况我遇到过太多次了。后来才发现&#xff0c;很多时候是因为某个程序偷偷吃掉了大量CPU或内存资…...

比Jenkins轻量10倍!用Gitea Actions搭建内网自动化部署的完整踩坑记录

企业级内网CI/CD革命&#xff1a;Gitea Actions轻量化实战指南 在当今快节奏的软件开发环境中&#xff0c;持续集成与持续部署(CI/CD)已成为企业提升交付效率的关键。然而&#xff0c;传统解决方案如Jenkins往往伴随着沉重的资源消耗和复杂的配置流程&#xff0c;让许多中小团队…...

从信任根到信任链:构建坚不可摧的数字信任体系

1. 信任根&#xff1a;数字世界的安全基石 想象一下你正在建造一座摩天大楼。无论设计多么精妙&#xff0c;如果地基不牢固&#xff0c;整栋建筑都可能坍塌。在数字安全领域&#xff0c;**信任根&#xff08;Root of Trust, RoT&#xff09;**就是这样的地基。它是一个密码系统…...