C++20中线程类std::jthread的使用 - 详解

news/2025/10/12 14:45:29/文章来源:https://www.cnblogs.com/tlnshuju/p/19136627

C++20中线程类std::jthread的使用 - 详解

2025-10-12 14:39  tlnshuju  阅读(0)  评论(0)    收藏  举报

      C++20中的std::jthread类表示一个执行线程。它与std::thread具有相同的常规行为,但std::jthread在析构(destruction)时会自动重新加入(rejoin),并且可以在某些情况下被取消/停止(cancelled/stopped)。

      与std::thread不同,std::jthread在逻辑上持有一个std::stop_source类型的内部私有成员,该成员维护一个共享的停止状态(stop-state)。std::jthread构造函数接受一个以std::stop_token作为第一个参数的函数,该参数由std::jthread从其内部std::stop_source传入。这使得该构造函数能够检查在执行过程中是否已请求停止,如果已请求则返回。

      std::jthread对象也可能处于不代表任何线程的状态(after default construction, move from, detach, or join),并且执行线程可能不与任何std::jthread 对象关联(after detach)。

任何两个std::jthread对象都不能代表同一个执行线程;std::jthread不可拷贝构造或拷贝赋值,但可移动构造和移动赋值。

      如果std::jthead无法启动,则抛std::system_error异常。

      std::jthread构造函数的参数按值移动或拷贝。如果需要将引用参数传递给线程函数,则必须对其进行包装(例如,使用std::ref或std::cref)

std::jthread的析构函数:如果当前线程有一个关联线程即joinable()为true,则会先调用request_stop(),然后再调用join()

      (1).如果std::jthread之前被请求stop,则调用request_stop()无效。

      (2).std::jthread对象在以下情况后没有关联线程:它是被默认构造的、它被移出(moved from)、已调用join()、已调用detach()。

      (3).如果join()抛出异常,则std::terminate()可能被调用。

      std::jthread中的函数:

      joinable():如果std::jthread对象标识了一个活动的执行线程,则返回true,否则返回false。已完成代码执行但尚未joined的线程仍被视为活动的执行线程,因此是jonable的

      get_id():返回std::jthread::id的值(std::thread::id的类型别名),用于标识与*this关联的线程。如果没有关联的线程,则返回默认构造的std::jthread::id。

      hardware_concurrency():静态函数,返回支持的并发线程数。该值仅供参考。如果该值定义不明确或无法计算,则返回0。

      join():阻塞当前线程,直到*this标识的线程完成执行。*this本身不执行同步。多个线程同时对同一个std::jthread对象调用join()会造成数据争用,从而导致未定义的行为。

      detach():将执行线程与std::jthread对象分离,允许继续独立执行。线程退出后,所有分配的资源都将被释放。调用detach后,*this不再拥有任何线程。

      swap:交换两个std::jthread对象的底层句柄。

      测试代码如下:

int test_jthread_constructor()
{auto func1 = [](int val) {for (auto i = 0; i < 2; ++i) {std::cout << ++val << std::endl;std::this_thread::sleep_for(100ms);}};auto func2 = [](int& val) {val = 88;};std::jthread jth1(func1, 5);std::jthread jth2{};std::cout << std::format("jth1 joinable: {}; jth2 joinable: {}", jth1.joinable(), jth2.joinable()) << std::endl;std::cout << "jth1 id: " << jth1.get_id() << "; jth2  id: " << jth2.get_id() << std::endl;jth2 = std::move(jth1);std::cout << std::format("jth1 joinable: {}; jth2 joinable: {}", jth1.joinable(), jth2.joinable()) << std::endl;std::cout << "jth1 id: " << jth1.get_id() << "; jth2  id: " << jth2.get_id() << std::endl;int val{ -1 };std::jthread jth3(func2, std::ref(val));jth3.join();std::cout << std::format("jth3 joinable: {}, val: {}", jth3.joinable(), val) << std::endl;std::cout << "jth3 id: " << jth3.get_id() << std::endl;std::cout << "concurrent threads are supported: " << std::jthread::hardware_concurrency() << std::endl;std::jthread jth4([] {std::cout << "jth4 running ..." << std::endl;std::this_thread::sleep_for(1s);std::cout << "jth4 end" << std::endl;});std::cout << "jth4 joinable: " << jth4.joinable() << ", id: " << jth4.get_id() << std::endl;jth4.detach();std::this_thread::sleep_for(3s);std::cout << "jth4 joinable: " << jth4.joinable() << ", id: " << jth4.get_id() << std::endl;jth4.swap(jth2);std::cout << std::format("jth2 joinable: {}; jth4 joinable: {}", jth2.joinable(), jth4.joinable()) << std::endl;std::swap(jth2, jth4);std::cout << std::format("jth2 joinable: {}; jth4 joinable: {}", jth2.joinable(), jth4.joinable()) << std::endl;return 0;
}

      执行结果如下图所示:

      get_stop_source():返回与std::jthread对象内部持有的相同共享停止状态相关联的std::stop_source。

      get_stop_token():返回与std::jthread对象内部持有的相同共享停止状态相关联的std::stop_token。

      request_stop():如果内部停止状态尚未收到停止请求,则向其发出停止请求。该判断以原子方式进行,如果已发出停止请求,则停止状态将以原子方式更新,以避免竞争条件(race conditions)。request_stop()只是向线程的std::stop_token发送"尽快退出"的信号,线程函数内要主动检查std::stop_token的stop_requested(),然后自行结束循环,不会结束线程,因此再调用joinable()还是true

int test_jthread_request_stop()
{std::jthread jth([](std::stop_token token) {while (!token.stop_requested()) {std::cout << "running ...\n";std::this_thread::sleep_for(500ms);}std::cout << "stopped\n";});std::this_thread::sleep_for(3s);std::cout << "jth joinable: " << jth.joinable() << ", id: " << jth.get_id() << std::endl;jth.request_stop();std::this_thread::sleep_for(1s);std::cout << "jth joinable: " << jth.joinable() << ", id: " << jth.get_id() << std::endl;return 0;
}

      执行结果如下图所示:

      std::jthread和std::thread区别:

      (1).std::jthread析构时会自动join(),无需手动调用join(),而std::thread析构前必选手动join()或detach()。

      (2).std::jthread内置停止令牌(stop_token),可通过std::stop_token请求线程停止

      (3).std::jthread兼容std::thread大多数接口。

      (4).std::jthread比std::thread更安全。

GitHub:https://github.com/fengbingchun/Messy_Test

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

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

相关文章

2025年CNC高压清洗机厂家权威推荐:高效清洁与耐用性能深

2025年CNC高压清洗机厂家权威推荐:高效清洁与耐用性能深在制造业智能化转型的浪潮中,CNC高压清洗机作为工业清洁领域的关键设备,正发挥着日益重要的作用。这类设备不仅能有效清除CNC加工中心、数控机床等精密设备在…

ABC427

ABC427C. Bipartize 枚举每个点的颜色,然后统计有多少条边的端点颜色相同,这就是要删除的点,取最小值即可代码实现 #include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i)using name…

C# NUnit

Install-Package NUnit; Install-Package NUnit3TestAdapter; Install-Package Microsoft.Net.Test.Sdk; Install-Package Moq;using Moq; using NUnit.Framework; using NUnit.Framework.Legacy;namespace ConsoleApp…

从 EFI 到 GPT:深入理解现代计算机启动与磁盘分区技能

从 EFI 到 GPT:深入理解现代计算机启动与磁盘分区技能pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…

2025年扁钢厂家最新权威推荐榜:强度与精度双重保障的工业脊

2025年扁钢厂家最新权威推荐榜:强度与精度双重保障的工业脊梁在制造业转型升级的关键时期,扁钢作为工业领域的"骨架材料",其质量直接影响着装备制造、建筑工程、轨道交通等行业的健康发展。随着新材料技术…

GJB 438C学习

系列标准宣贯︱GJB 438C中规定软件文档的用途与编写时机长风破浪会有时,直挂云帆济沧海! 可通过下方链接找到博主 https://www.cnblogs.com/judes/p/10875138.html

typora markdown

markdown学习 标题: +空格+标题名字 二级标题 +名称 以此类推每级加一个# 字体 hello,world! 左右 ** hello,world! * hello,workd! *** hello,workd! …

2025防爆数粒机厂家权威推荐榜:高效精准与安全防爆口碑之选

2025防爆数粒机厂家权威推荐榜:高效精准与安全防爆口碑之选在制药、化工、食品等工业领域,颗粒物料的精准计数与分装是生产流程中的关键环节。防爆数粒机作为特种设备,不仅需要满足高效精准的计数要求,更要具备严格…

想在浏览器里跑 AI?TensorFlow.js 硬件帮助完全指南

想在浏览器里跑 AI?TensorFlow.js 硬件帮助完全指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&quo…

Linux系统设置与理解主机名(hostname)的重要性

在Linux系统中,主机名(hostname)是区分网络中一台主机或者是服务设备的一个唯一标识。操作系统在网络通讯时会使用到主机名,它允许用户和程序方便地识别和交互。除了作为识别符,主机名在系统安全性、维护管理方面也…

CSharp: image (JPG,PNG,etc) covert webp using Aspose.Imaging

protected void Page_Load(object sender, EventArgs e){if (!IsPostBack){// 激活Aspose//ActiveAspose(); ///无效HookManager.ShowHookDetails(true);HookManager.StartHook();// The path to the documents direct…

基于GPT2搭建医疗问诊机器人

基于GPT2搭建医疗问诊机器人2025-10-12 14:23 dribs 阅读(0) 评论(0) 收藏 举报1

2025耐磨轮胎厂家最新权威推荐榜:超强抓地力与持久耐用深度

2025耐磨轮胎厂家最新权威推荐榜:超强抓地力与持久耐用深度在商用车运输领域,轮胎作为车辆与路面唯一接触的部件,其耐磨性能直接关系到运营成本与行车安全。据统计,轮胎磨损占运输企业运营成本的比重不容忽视,优质…

在Vue 3项目中集成Element Plus组件库的步骤

安装Element Plus 首先,确保你的开发环境已经安装了Node.js和npm(或yarn)。然后,在你的Vue 3项目根目录下打开终端,并执行以下命令来安装Element Plus: npm install element-plus --save # 或者使用yarn yarn ad…

安装pytorch(win 11 +3060 laptop)

移除不兼容的pytorch版本运行代码时报错这个错误表明正在使用的 PyTorch 版本过旧,它不支持 torch.utils.data.DataLoader 的 persistent_workers 参数或属性。 卸载旧版 pip uninstall torch torchvision torchaudio…

MySQL数据库连接过多(Too many connections)错误处理策略

MySQL数据库遭遇“Too many connections”错误时,意味着当前所有可用的连接都已被使用,新的客户端连接无法建立。处理这一问题需要综合考虑配置调整、资源优化和代码改进等多方面因素。 首先,检查 max_connections设…

Real English Questions and Answers Practice

Real English Questions and Answers PracticeHello my friends and welcome back to Bookish English 2, the place where you live English, not just study it. Todays lesson is special. You will not read gramm…

[Python] Python配置uv环境

[Python] Python配置uv环境$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录01 安装uv02 创建项目03 uv安装python包3.1 uv add3.2 uv pip install(兼容…

SQL删除操作性能分析:移除300万条记录所需时间估算

数据库服务器硬件CPU: 删除操作会消耗CPU资源。如果处理器速度较慢或者负载较高,这将直接影响到删除操作的速度。 内存: 足够快速且充足量内存可以确保数据库缓冲区高效运行。 磁盘I/O: 删除大量数据会产生大量磁盘I/…

Spring Boot 基础教程 - 指南

Spring Boot 基础教程 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…