理解 std::thread::detach

news2024/11/29 0:38:00

C++多线程并发编程入门(目录)

detach 的作用

detach 的作用就是让线程独自执行。

为何需要 detach

在 理解 std::thread::join 中,我们看到了,如果所有线程都是一开始就在 main 函数中创建好的,那么只需要有一个 join 函数就足够了。

但是 在 理解 std::thread::join 中,我们也已经发现了线程嵌套时,join的弊端。

为了解决 join的弊端,detach 也就出现了。

也就是 detach 仅仅是让线程独立执行,并不会让调用它的线程等待它。

这样线程运行起来之后,就和其他任何线程都没有了瓜葛。

各自独立放飞自我,没人管,没人问。

代码验证(detach)

我们将 理解 std::thread::join 中的第2个示例代码,record 线程的执行由 join 改为 detach。

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
using namespace std::chrono;

void record()
{
    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(1));
    cout << "record finished!" << endl;
}

void ui_fun()
{
    std::cout << "starting record ...\n";
    std::thread record_thread(record);
    record_thread.detach();

    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(5));
    cout << "ui_fun finished!" << endl;
}

int main()
{
    auto start = std::chrono::system_clock::now();

    std::cout << "starting ui_fun ...\n";
    std::thread helper1(ui_fun);

    std::cout << "waiting for ui_fun to finish..." << std::endl;
    helper1.join();

    auto elapsed = chrono::duration_cast<chrono::seconds>(system_clock::now() - start).count();
    std::cout << "done! elapsed " << elapsed << " seconds.";
}

执行结果

可以看到,由于 UI线程没有等待 record 线程,所以, record 是在 UI线程执行的过程中自己独立执行完成的。

从而两个线程 ui_fun record 同时执行,整个程序执行的时间就变短了。

而此时 main 只是在等待 ui_fun线程的退出。

执行示意图

只有main线程在等待UI线程,record是一个野线程

此时,只有main线程在等待UI线程,record是一个野线程。

好在record执行的时间短。

如果record执行的时间比ui_fun线程时间长呢?比如,窗口关闭了,录制写文件由于比较慢,还没完成。那岂不是要丢数据了?

detach 的弊端(野线程)

下面我们就来模拟 record 线程确实是比较慢,UI线程都被用户关闭窗口了,还没有把所有的录制数据写入到本地文件。

代码验证(detach野线程执行耗时操作)

完整代码:我们把 record 线程的执行时间由 原来的 1秒 改为 11秒。

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
using namespace std::chrono;

void record()
{
    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(11));
    cout << "record finished!" << endl;
}

void ui_fun()
{
    std::cout << "starting record ...\n";
    std::thread record_thread(record);
    record_thread.detach();

    // simulate expensive operation
    std::this_thread::sleep_for(std::chrono::seconds(5));
    cout << "ui_fun finished!" << endl;
}

int main()
{
    auto start = std::chrono::system_clock::now();

    std::cout << "starting ui_fun ...\n";
    std::thread helper1(ui_fun);

    std::cout << "waiting for ui_fun to finish..." << std::endl;
    helper1.join();

    auto elapsed = chrono::duration_cast<chrono::seconds>(system_clock::now() - start).count();
    std::cout << "done! elapsed " << elapsed << " seconds.";
}

执行结果

可以看到,没有出现 record finished

我们可以看到,main 线程等到UI线程执行完就退出了。

main退出意味着整个进程退出,操作系统会回收一切。

这个时候 record 线程虽然还没执行完,但是也被操作系统(强拆)回收了。

这太糟糕了。程序没有正常的退出。

执行示意图

record 成了一个野线程,还没执行完,被系统强制回收

所以,main还是要等待所有线程退出的。

作为所有模块最后退出的保障,main必须是最后一个退出才行。

detach 的正确用法

通过上面的案例分析,我们可以知道 detach 线程函数内部必须要要是一个无限循环。

并且有退出条件,而退出条件必须由外部设置。

同时,detach 线程内部要一直等待这个退出条件。

main 函数需要增加代码来触发这个 detach 线程的退出条件。从而变成了 detach 在启动的时候是以 detach 方式启动(不阻塞其他任何线程),同时 main 以代码的方式 等待(join)这个detach 线程。

由于具体的代码比较复杂,这里就不做完整的展示了。

我会在 本专栏 C++多线程并发编程入门(目录) 的后续文章中展示。

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

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

相关文章

香橙派Orangepi Zero2 刷机步骤

目录 1.香橙派Orangepi Zero2简介 2.刷机 2.1物料准备 2.2 格式化SD卡 2.3 烧录镜像到SD卡 2.4 安装SD卡到Orangepi 2.5 连接Pi电源 2.6 MobaXterm 串口登陆Orangepi 2.6.1 连线示意图 2.6.2 MobaXterm 使用 2.6.3修改登陆密码 2.6.4 网络配置 2.7 SSH登陆开发版…

3D封装技术发展

长期以来&#xff0c;芯片制程微缩技术一直驱动着摩尔定律的延续。从1987年的1um制程到2015年的14nm制程&#xff0c;芯片制程迭代速度一直遵循摩尔定律的规律&#xff0c;即芯片上可以容纳的晶体管数目在大约每经过18个月到24个月便会增加一倍。但2015年以后&#xff0c;芯片制…

手把手教你申请腾讯云免费SSL证书

2023腾讯云免费SSL证书申请流程&#xff0c;一个腾讯云账号可以申请50张免费SSL证书&#xff0c;免费SSL证书为DV证书&#xff0c;仅支持单一域名&#xff0c;申请腾讯云免费SSL证书3分钟即可申请成功&#xff0c;免费SSL证书品牌为TrustAsia亚洲诚信&#xff0c;腾讯云百科分享…

[深度学习]大模型训练之框架篇--DeepSpeed使用

现在的模型越来越大&#xff0c;动辄几B甚至几百B。但是显卡显存大小根本无法支撑训练推理。例如&#xff0c;一块RTX2090的10G显存&#xff0c;光把模型加载上去&#xff0c;就会OOM&#xff0c;更别提后面的训练优化。 作为传统pytorch Dataparallel的一种替代&#xff0c;D…

技术干货 —— 手把手教你通过缓存提升 API 性能

许多开发者都希望能够彻底搞清楚 API 的工作方式&#xff0c;以及如何利用缓存 API 请求来提升业务&#xff0c;但是当这个需求进入实现阶段时&#xff0c;许多人就会发现手头并没有合适的工具和恰当的方法&#xff0c;所以我们今天就为大家做一个全面的讲解&#xff1a; ① 几…

Python的由来和基础语法(一)

目录 一、Python 背景知识 1.1Python 是咋来的? 1.2Python 都能干啥? 1.3Python 的优缺点 二、基础语法 2.1常量和表达式 2.2变量和类型 变量的语法 (1) 定义变量 (2) 使用变量 变量的类型 (1) 整数 (2) 浮点数(小数) (3) 字符串 (4) 布尔 (5) 其他 动态类型…

NAT与代理服务器

1.DNS Domain Name System 是一整套从域名映射到IP的系统&#xff08;把域名转化为IP地址&#xff09; 2.域名简介 3.周鸿祎 傅盛 4.ICMP协议 用来网络故障排查原因 草图理解“位置” ping ICMP 是绕过TCP UDP传输协议的&#xff0c;没有端口号 traceroute 5.NAT技术 N…

Shell脚本练习——系统应用相关

显示系统信息 [rootwenzi data]#cat systemInfo.sh #/bin/bash RED"\E[1;31m" GREEN"\E[1;32m" END"\E[0m" echo -e "$GREEN----------------------Host systeminfo--------------------$END" echo -e "HOSTNAME: $REDho…

论文阅读:Distortion-Free Wide-Angle Portraits on Camera Phones

论文阅读&#xff1a;Distortion-Free Wide-Angle Portraits on Camera Phones 今天介绍一篇谷歌 2019 年的论文&#xff0c;是关于广角畸变校正的。 Abstract 广角摄影&#xff0c;可以带来不一样的摄影体验&#xff0c;因为广角的 FOV 更大&#xff0c;所以能将更多的内容…

git ------ IDEA中建立本地/远程仓库及上传

目录 建立本地仓库 1. idea中选择创建本地仓库 选择目标文件 创建远程仓库 1.码云上进行库创建 将本地仓库数据提交到远程仓库 提交代码 推送到远程 建立本地仓库 1. idea中选择创建本地仓库 或 vsm中找下列2 即可 选择目标文件 成功后会出现以下标识 更新 提交 推…

YOLO目标检测——室内场景识别数据集下载分享

目标检测室内场景识别数据集可以广泛应用于各种需要对室内场景进行目标识别和跟踪的领域&#xff0c;包括安防监控、智能家居、物流仓储管理等 数据集点击下载&#xff1a; YOLO室内场景识别数据集&#xff08;一&#xff09;5950图片26类别.rar YOLO室内场景识别数据集&#…

基础算法--快速排序

快速排序 算法原理 1. 取一个元素p(第一个元素&#xff0c;最后一个元素&#xff0c;中间元素&#xff0c;随机 都可以)&#xff0c;使元素p归位。 2. 列表被p分成两部分&#xff0c;左边都比p小&#xff0c;右边都比p大。 3. 递归完成排序。 动态演示 python代码实现 import…

Code Snippet的使用

文章目录 前言Code Snippet:就是咱们在VS中敲的prop、propfull、ctol【构造器快捷键】、for等快捷键&#xff0c;然后按tab键自动生成代码1.VS自带的&#xff1a;prop、propfull、ctol【构造器快捷键】、for等快捷键&#xff0c;直接使用2.自定义Snippet&#xff1a; 巨人的肩膀…

深度学习入门教学——卷积神经网络CNN

目录 一、CNN简介 一、输入层 二、卷积层 三、池化层 四、全连接层 一、CNN简介 1、应用领域 检测任务 分类与检索 超分辨率重构 2、卷积网络与传统网咯的区别 传统神经网络和卷积神经网络都是用来提取特征的。神经网络&#xff1a; 可以将其看作是一个二维的。卷积神经…

力扣:随即指针138. 复制带随机指针的链表

复制带随机指针的链表 OJ链接 分析&#xff1a; 该题的大致题意就是有一个带随机指针的链表&#xff0c;复制这个链表但是不能指向原链表的节点&#xff0c;所以每一个节点都要复制一遍 大神思路&#xff1a; ps:我是学来的 上代码&#xff1a; struct Node* copyRandomList(s…

3D DRAM:突破内存瓶颈的新希望

DRAM&#xff0c;动态随机存储器&#xff0c;是一种在计算机、消费电子、通信等领域广泛应用的内存技术。它的主要特点是在同一周期内可以随机读取或写入单字节数据&#xff0c;使得其在各种计算应用中成为不可或缺的组件。 DRAM的发展历程充满了戏剧性和技术革新。最早的DRAM诞…

【5】openGL使用宏和函数进行错误检测

当我们编写openGL程序&#xff0c;没有报编译链接错误&#xff0c;但是运行结果是黑屏&#xff0c;这不是我们想要的。 openGL提供了glGetError 来检查错误&#xff0c;我们可以通过在运行时进行打断点查看glGetError返回值&#xff0c;得到的是一个十进制数&#xff0c;将其转…

Jenkins+maven+testng+htmlreport单元自动化测试

背景说明 为了可以在jenkins自动化运行单元测试的代码&#xff0c;所以使用maventestng的技术结合&#xff0c;达到手动或者定时去执行单元测试的代码&#xff0c;以便提高人工运行的自动化的效率。单元通过该方案也可以套用在httpclient框架去执行测试web api接口的自动化测试…

SILERGY(矽力杰)功率电子开关 SY6280AAC

SILERGY(矽力杰)功率电子开关 SY6280AAC Low Loss Power Distribution Switch SOT-5 Pacakge 2.4V ~ 5.5V (<6V) 0.6W Max. Current 2A Reverse blocking (no body diode) Programmable current limit ( Ilimits(A) 6800 / Rset(ohm). ) Application Circuit (Reco…

跳出Lambda表达式forEach()循环解决思路

背景 在一次需求开发时&#xff0c;发现使用Lambda的forEach()跳不出循环。如下示例代码&#xff0c;想在遍历满足条件时跳出循环。 public static void main(String[] args) {List<Integer> list Arrays.asList(1, 4, 5, 7, 9, 11);list.forEach(e -> {if (e % 2 …