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

C++ 20新特性之线程与jthread

💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。

为什么要引入jthread

        在C++ 11中,已经引入了std::thread。std::thread为C++标准库带来了一流的线程支持,极大地促进了多线程开发的便利性。但std::thread也存在一些明显的不足和短板,主要有以下几点。

        1、生命周期管理的复杂性。std::thread对象必须在它代表的线程结束之前,一直保持存活。如果一个std::thread对象被销毁(比如:离开了其作用域),而它关联的线程还在运行,那么程序会调用std::terminate()终止,除非线程被join或者detach过。这就要求我们必须仔细管理每个线程对象的生命周期,大大增加了编码的复杂度和出错的可能性。

        2、缺乏自动资源管理。std::thread没有自动管理线程生命周期的机制,程序员必须显式调用join或detach。否则,可能导致资源泄露或程序异常终止,这在异常处理场景下尤为麻烦。

        3、异常安全性问题。如果在创建或启动std::thread时发生异常,可能会导致资源泄露或者程序的不确定行为。比如:如果在std::thread构造函数中抛出了异常,那么已经创建的线程可能无法正确地被join或detach。

        为了解决这些问题,C++ 20中引入了std::jthread。

自动管理生命周期

        C++ 20中新引入的std::jthread解决了C++ 11中std::thread的一些不便之处,特别是在线程生命周期管理上的自动化处理。std::jthread是一个智能指针风格的类,它自动join或detach与之关联的线程,从而避免了潜在的资源泄露问题。

        接下来,我们通过一个具体的例子来理解std::jthread的工作原理。

#include <iostream>
#include <thread>
using namespace std;void RunTask(stop_token stoken)
{int nCount = 0;while (!stoken.stop_requested()){cout << "Task running... " << nCount++ << endl;this_thread::sleep_for(chrono::seconds(1));}cout << "Task stopped" << endl;
}int main()
{jthread t(RunTask);// 主线程等待一段时间this_thread::sleep_for(chrono::seconds(5));return 0;
}

        在上面的示例代码中,RunTask函数作为工作线程的入口点,接收一个std::stop_token参数,用于检测是否请求停止。std::jthread t(RunTask)声明了一个jthread对象t,它会自动管理task函数所在线程的生命周期。当main函数结束时,t会自动调用join,等待关联线程完成或终止。可以看到,虽然我们没有显式要求停止线程,但当main函数返回时,jthread会确保线程安全结束。执行这段代码,其输出如下。

Task running... 0
Task running... 1
Task running... 2
Task running... 3
Task running... 4
Task stopped

stop_source和stop_token

        与std::thread相比,std::jthread的强大之处在于它与std::stop_source和std::stop_token的集成,从而允许我们优雅地请求线程停止。

        在下面的示例代码中,通过创建std::stop_source对象,并将其get_token方法的结果传递给RunTask函数,我们可以在需要时通过stopSource.request_stop()请求线程停止。RunTask函数中会循环检查std::stop_token的状态,一旦请求停止,就会退出循环并清理资源。

#include <iostream>
#include <thread>
using namespace std;void RunTask(stop_token stoken)
{int nCount = 0;while (!stoken.stop_requested()){// 子线程执行一些任务cout << "Working..." << nCount++ << endl;this_thread::sleep_for(chrono::seconds(1));}cout << "Task stopped" << endl;
}int main()
{stop_source stopSource;jthread t(RunTask, stopSource.get_token());// 主线程等待一段时间this_thread::sleep_for(chrono::seconds(3));cout << "Request task to stop..." << endl;// 主动请求线程停止stopSource.request_stop();return 0;
}

        执行上述代码,其输出如下。

Working...0
Working...1
Working...2
Request task to stop...
Task stopped

线程中使用成员函数

        std::jthread不仅可以用来启动普通函数,还可以用来启动类的成员函数。此时,需要使用lambda表达式来传递对象实例和成员函数指针。具体的用法,可以参考下面的示例代码。

#include <iostream>
#include <thread>
using namespace std;class CTask
{
public:void Run(stop_token stoken){int nCount = 0;while (!stoken.stop_requested()){cout << "Working..." << nCount++ << endl;this_thread::sleep_for(chrono::seconds(1));}}
};int main()
{CTask task;jthread t([&task](stop_token stoken){ task.Run(stoken); });this_thread::sleep_for(chrono::seconds(5));return 0;
}

        在上面的示例代码中,我们首先定义了一个名为CTask的类,其中包含一个公共成员函数Run。这个函数接收一个stop_token参数,用于检查是否有停止线程的请求。函数内部,它使用一个循环不断地输出计数器的值,并在每次循环之间暂停1秒。当stop_token表示停止请求时,循环结束。

        在main函数中,我们创建了CTask类的对象task。接着,声明了一个jthread对象t,并初始化它以执行一个Lambda函数。这个Lambda函数捕获了task对象的引用,并将其传递给task.Run()方法,同时也传入了stop_token。jthread会自动为这个Lambda函数提供一个与之关联的stop_token,用于线程的停止请求。当jthread对象t的生命周期结束时,它会自动调用join来等待线程结束,无需手动调用join或detach。

相关文章:

C++ 20新特性之线程与jthread

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 为什么要引入jthread 在C 11中&#xff0c;已经引入了std::thread。std::thread为C标准库带来了一流的线程支持&#xff0c;极大地促进了多线程…...

赶紧收藏!2024 年最常见 20道并发编程面试题(七)

上一篇地址&#xff1a;赶紧收藏&#xff01;2024 年最常见 20道并发编程面试题&#xff08;六&#xff09;-CSDN博客 十三、什么是线程局部存储&#xff08;Thread-Local Storage&#xff09;&#xff1f; 线程局部存储&#xff08;Thread-Local Storage&#xff0c;简称TLS…...

HAL库开发--第一盏灯

知不足而奋进 望远山而前行 目录 文章目录 前言 学习目标 学习内容 需求 开发流程 项目创建 芯片配置 功能配置 时钟配置 项目配置 编写代码 编译测试 烧录失败解决 ​编辑 总结 前言 在嵌入式系统开发中&#xff0c;掌握HAL库开发流程、STMCubeMX配置过程以及…...

Linux C语言:变量的作用域和生命周期(auto、register、static和extern)

一、变量存储类型-auto 1、auto变量的说明 变量在程序中使用时,必须预先说明它们的存储类型和数据类型。 变量说明的一般形式是&#xff1a; <存储类型> <数据类型 > <变量名> &#xff1b; <存储类型>是关键词auto、register、static和extern<…...

AI Stable diffusion 报错:稳定扩散模型加载失败,退出

可能是内存不够&#xff0c;看看你最近是加了新的大的模型&#xff0c;可以把你的stable-diffusion-webui\models\Stable-diffusion目录下的某个ckpt删除掉&#xff0c;可能ckpt太大&#xff0c;无法加载成功&#xff1b; Stable diffusion model failed to load, exiting 如图…...

[Python学习篇] Python循环语句

while 循环 语法&#xff1a; while 条件: 条件成立后会重复执行的代码 ...... 示例1&#xff1a;死循环 # 这是一个死循环示例 while True:print("我正在重复执行")示例2&#xff1a;循环指定次数 i 1 while i < 5:print(f"执行次数 {i}")…...

MongoDB 正则表达式

MongoDB 正则表达式 MongoDB 是一个流行的 NoSQL 数据库&#xff0c;它提供了强大的查询功能&#xff0c;包括对正则表达式的支持。正则表达式是一种强大的文本搜索工具&#xff0c;它允许用户根据特定的模式匹配和搜索字符串。在 MongoDB 中&#xff0c;正则表达式可以用于查…...

Django配置连接池:使用django-db-connection-pool配置连接池

一、该三方库文档使用 github地址&#xff1a; https://github.com/altairbow/django-db-connection-pool/blob/1.2.5/README_CN.mdhttps://github.com/altairbow/django-db-connection-pool/blob/1.2.5/README_CN.md1、选择指定版本&#xff0c;查看指定版本的文档和配置&am…...

SpringBoot整合钉钉实现消息推送

前言 钉钉作为一款企业级通讯工具&#xff0c;具有广泛的应用场景&#xff0c;包括但不限于团队协作、任务提醒、工作汇报等。 通过Spring Boot应用程序整合钉钉实现消息推送&#xff0c;我们可以实现以下功能&#xff1a; 实时向指定用户或群组发送消息通知。自定义消息内容…...

【机器学习】集成学习方法:Bagging与Boosting的应用与优势

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、集成学习的定义二、Bagging方法1. 随机森林&#xff08;Random Forest&#xff09;2. 其他Bagging方法 二、Boosting方法1. 梯度提升树&#xff08;Gradient Boosting Machine, GBM&#xff09;解释GBM的基本原理和…...

工业 web4.0 的 UI 卓越非凡

工业 web4.0 的 UI 卓越非凡...

C语言 | Leetcode C语言题解之第145题二叉树的后序遍历

题目&#xff1a; 题解&#xff1a; void addPath(int *vec, int *vecSize, struct TreeNode *node) {int count 0;while (node ! NULL) {count;vec[(*vecSize)] node->val;node node->right;}for (int i (*vecSize) - count, j (*vecSize) - 1; i < j; i, --j)…...

如何在 Vue 3 中使用 vue3-print-nb 实现灵活的前端打印

你好&#xff0c;我是小白Coding日志&#xff0c;一个热爱技术的程序员。在这里&#xff0c;我分享自己在编程和技术世界中的学习心得和体会。希望我的文章能够给你带来一些灵感和帮助。欢迎来到我的博客&#xff0c;一起在技术的世界里探索前行吧&#xff01; 前言 在前端开…...

Go Module详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

基于51单片机的智能水表

一.硬件方案 本设计主要以51单片机作为主控处理器的智能水表&#xff0c;该水表能够记录总的用水量和单次用水量&#xff0c;当用水量超出设定值时系统发出声光报警提醒&#xff0c;水量报警值能够通过按键进行自行设置&#xff0c;并且存储于AT24C02中&#xff0c;并且可以测…...

SQLServer 借助Navcate做定时备份的脚本

首先创建SQLServer链接&#xff0c;然后在Query标签种创建一个查询 查询内容如下 use ChengYuMES declare ls_time varchar(1000) declare ls_dbname varchar(1000) set ls_time convert(varchar, getdate(), 112) _ replace(convert(varchar, getdate(), 108), :, )-- 需…...

MBD_入门篇_21_SimulinkSignalAttributes

21.SignalAttributes 21.1 概述 Signal Attributes&#xff0c;信号属性&#xff0c;信号特性。 21.2 回顾常用模块 21.2.1 DataTypeConversion 数据类型转换模块&#xff0c;可以对信号的数据类型进行强制转换。无符号数据与有符号数据相加&#xff0c;我们可以将无符号数据转…...

Web前端高级课程:深入探索与技能飞跃

Web前端高级课程&#xff1a;深入探索与技能飞跃 在数字化时代的浪潮中&#xff0c;Web前端技术日新月异&#xff0c;对前端开发者的技能要求也日益提高。为了满足这一需求&#xff0c;我们精心打造了一款Web前端高级课程&#xff0c;旨在帮助学员掌握最前沿的前端技术&#x…...

螺丝工厂vtk ThreadFactory(1)

螺丝工厂vtkThreadFactory (1) 缘起 几年前的探索在Python里应用Openscad实现3D建模之3D螺纹建模初探3 新的参考: generating nice threads in openscadvtkRotationalExtrusionFilter 辅助AI: coze 笔记&#x1f4d2;: openscad 代码分析 // 半径缩放函数&#xff0c;用…...

Android13 蓝牙协议属性配置详解

Android13 蓝牙协议属性配置详解 文章目录 Android13 蓝牙协议属性配置详解一、前言二、Android13 蓝牙协议属性配置1、Profile 属性和暴露接口的定义2、蓝牙协议属性定义3、系统代码中判断蓝牙协议是否使能的代码 三、其他1、adb 窗口中查看蓝牙协议属性2、动态设置蓝牙prop协…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...