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

C++一文讲透thread中的detach和join的差别

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、thread详解
  • 二、线程何时运行
  • 三、线程启动方式
    • 1.join
    • 2.detach
  • 总结


前言

无论哪种语言线程在绝大多数项目中都是会用到的,C++也一样,C++包装了一个std::thread类可以简化程序员的编程,但在使用过程中也要注意区分用法,否则可能适得其反。

今天要讨论的就是单纯的thread的join(等待)和detach(分离)两种情景,让不懂得人看完之后茅塞顿开。


一、thread详解

C++标准库成员,是对线程的包装类,在thread头文件里面,使用方式是std::thread。创建线程本身就是通过创建一个thread类对象然后和系统线程完成绑定(映射),这样可以通过操作thread类对象来管理创建的系统线程,系统线程本身行为受到内核调度机制影响。

示例代码:

#include <iostream>
#include <thread>// 线程函数
void threadFunction() {std::cout << "Thread function is running" << std::endl;
}int main() {// 创建线程并启动std::thread t(threadFunction);// 等待线程完成t.join();std::cout << "Main thread is running" << std::endl;return 0;
}

注意:这个地方如果不使用t.join()可能导致main线程早于子线程结束,引发terminate!

二、线程何时运行

这个问题一定要说清楚才行,我以前用java的时候线程有一个start()可以决定什么时候启动线程,C++则不是这样,C++没有一个明确方法决定线程何时运行,只需要满足创建并等待(一般时间很短,取决于实际情况),直到线程获取了资源之后就会自动运行,而不需要显式调用方法。且无论是以join还是detach方式启动的线程都受到内核的调度。

三、线程启动方式

1.join

主线程(创建子线程的那个线程)等待子线程执行完毕才进行下一步,适合那种需要立刻得到结果的场景。创建方式很简单,你只需要先创建线程然后在合适的时候调用t.join()等待结束即可。

示例代码:

#include <iostream>
#include <thread>int main() {std::thread t([]{std::cout << "Lambda function is running" << std::endl;});t.join();std::cout << "Main thread is running" << std::endl;return 0;
}

当调用t.join()方法时主线程的等待,直到t线程结束主线程才会继续运行,程序结束。如果子线程里面有死锁主线程就会一直等待,永无休止。

2.detach

在C++中,std::thread提供了一个detach方法,可以将线程从其控制对象中分离。分离的线程会在后台独立运行,直到完成。此方法常用于不需要同步或获取线程结果的情况。不过,在使用detach时需要小心,因为主线程不能再控制或管理该分离的线程,这可能会导致资源管理和程序结束时的问题。

另外,detach之后的变量不能重新join。

示例代码:

#include <iostream>
#include <thread>
#include <chrono>void worker() {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Worker thread finished\n";
}int main() {std::thread t(worker);// 分离线程t.detach();std::cout << "Main thread finished\n";// 此处主线程可能已经结束,而分离的线程仍在运行std::this_thread::sleep_for(std::chrono::seconds(3));  // 确保主线程不会立即退出return 0;
}

创建的子线程很快就会结束,所以主线程3秒的休眠足够了,如果子线程超过3秒就会导致主线程早于子线程结束,程序terminate。

terminate called without an active exceptionProcess finished with exit code 3

所以,还是要面对一个问题,detach后的线程怎么管理?我并不能时时刻刻知道线程的状态,如果主线程结束了子线程没结束怎么办?方法还是有的,那就是增加标志位(同步需要atomic或锁),如果我想一个线程结束只需要修改标志位。比如下面的代码:

#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>std::atomic<bool> keepRunning(true); // 原子布尔变量,用于控制线程执行void threadFunction() {while (keepRunning) {std::cout << "Thread is running..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Thread stopped." << std::endl;
}int main() {std::thread t(threadFunction);// 主线程等待一段时间后停止子线程std::this_thread::sleep_for(std::chrono::seconds(5));keepRunning = false; // 设置标志位,通知线程停止t.join(); // 等待线程结束std::cout << "Main thread is running" << std::endl;return 0;
}

还可以借助boost库的方法来打断线程。例如:

#include <iostream>
#include <boost/thread.hpp>void threadFunction() {try {while (true) {// 执行一些工作boost::this_thread::interruption_point();}} catch (boost::thread_interrupted&) {std::cout << "Thread interrupted." << std::endl;}
}int main() {boost::thread t(threadFunction);// 主线程等待一段时间后中断子线程boost::this_thread::sleep_for(boost::chrono::seconds(5));t.interrupt(); // 中断线程t.join(); // 等待线程结束std::cout << "Main thread is running" << std::endl;return 0;
}

切记,不要随意中断线程,防止资源泄露!不管是标志位、条件判断还是boost库都必须考虑资源回收的问题,否则如果子线程里面使用了自由存储将永远无法得到回收。


总结

不管哪种方式启动的线程都要保证资源的回收,特别是当心主线程早于子线程结束的情况。还有一种容易让人疏忽的情况:如果你在一个函数里创建了thread对象,你没有join或detach,如果在函数return前线程没被回收就会导致terminate。比如,下面的代码:

void test(){
}void thread_join_detach(){std::thread t(test);
//    t.detach();
//    t.join();
}int main() {thread_join_detach();return 0;
}

上面的代码thread_join_detach函数返回会回收t对象,如果线程t还没结束就会terminate。解决方法有很多,比较简单的就是在函数return之前调用join或detach,还有就是把t提升作用域,比如全局变量。

相关文章:

C++一文讲透thread中的detach和join的差别

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、thread详解二、线程何时运行三、线程启动方式1.join2.detach 总结 前言 无论哪种语言线程在绝大多数项目中都是会用到的&#xff0c;C也一样&#xff0c;C…...

当Windows台式电脑或笔记本电脑随机关机时,请先从这8个方面检查

序言 你的Windows笔记本电脑或PC是否意外关闭?笔记本电脑电池故障、电源线松动、过热、电源设置错误、驱动程序过时或电脑组件故障等问题都可能是罪魁祸首。如果你对这个问题感到沮丧,试试这些解决方案。 进行一些初步检查 与从电池中获取电力的笔记本电脑不同,台式电脑依…...

【凤凰房产-注册安全分析报告-缺少轨迹的滑动条】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…...

【建议收藏】逻辑回归面试题,机器学习干货、重点。

. . . . . . . . . . .纯 干 货 . . . . . . . . . . . .今天是机器学习面试题&#xff0c;16大块的内容&#xff0c;124个问题总结的第二期&#xff1a;逻辑回归面试题。 逻辑回归是一种用于解决分类问题的统计学习方法&#xff0c;尤其在二分类…...

C++使用教程

目录 一、软件使用 二、C基础规则补充 关键字 整型取值范围 浮点型取值范围 字符型使用规则 字符串型使用规则 布尔类型 常用的转义移字符 三、数组、函数、指针、结构体补充 1.数组 2.函数 声明&#xff1a; 分文件编写&#xff1a; 值传递&#xff1a; 3.指…...

k8s volcano + deepspeed多机训练 + RDMA ROCE+ 用户权限安全方案【建议收藏】

前提&#xff1a;nvidia、cuda、nvidia-fabricmanager等相关的组件已经在宿主机正确安装&#xff0c;如果没有安装可以参考我之前发的文章GPU A800 A100系列NVIDIA环境和PyTorch2.0基础环境配置【建议收藏】_a800多卡运行环境配置-CSDN博客文章浏览阅读1.1k次&#xff0c;点赞8…...

设计模式(七)创建者模式之建造者模式

这里写目录标题 概述需求需求类图BikeBuilderMobikeBuilderOfoBuilderDirectorClientClient优缺点使用场景 模式扩展ComputerClient创建者模式对比工厂方法模式VS建造者模式抽象工厂模式VS建造者模式 总结 概述 建造者模式又叫生成器模式&#xff0c;是一种对象构建模式。它可…...

# class中的__call__方法解析

class中的__call__方法解析 文章目录 class中的__call__方法解析1. 为什么要有call&#xff0c;什么情况下用call&#xff1f;1.1 为什么要有 __call__ 方法1.2 没有 __call__ 方法是否可以1.3 使用 __call__ 方法的典型场景1.3.1 示例1&#xff1a;简单函数对象1.3.2 示例2&am…...

React逻辑复用的方式都有哪些

在日常开发中&#xff0c;能够优雅的复用组件和逻辑&#xff0c;是优秀开发者的职责。在react中&#xff0c;复用逻辑的方式有很多&#xff0c;可以适用于不同的业务场景。今天说三个比较有代表性的&#xff0c;Render Props、HOC、Hooks Render Props 创建一个接受函数作为其…...

【LinuxC语言】线程重入

文章目录 前言线程重入是什么线程重入实现示例代码总结前言 在并发编程中,我们经常需要处理多个线程同时访问和修改共享资源的问题。这可能会导致数据竞争和状态不一致,从而使程序的行为变得不可预测。为了解决这个问题,我们引入了一种称为“线程重入”的机制。线程重入,或…...

【Streamlit学习笔记】Streamlit-ECharts箱型图添加均值和最值label

Streamlit-ECharts Streamlit-ECharts是一个Streamlit组件&#xff0c;用于在Python应用程序中展示ECharts图表。ECharts是一个由百度开发的JavaScript数据可视化库Apache ECharts 安装模块库 pip install streamlitpip install streamlit-echarts绘制箱型图展示 在基础箱型…...

Docker镜像仓库:存储与分发Docker镜像的中央仓库

探索Docker镜像仓库&#xff1a;存储与分发Docker镜像的中央仓库 如果你是Docker的新手&#xff0c;或者已经在使用Docker但还不太了解Docker镜像仓库&#xff0c;那么这篇博客将是你的最佳指南。我们将从基础概念开始&#xff0c;逐步深入&#xff0c;帮助你全面掌握Docker注…...

FreeRTOS必考面试题及参考答案

什么是RTOS?FreeRTOS是什么?它主要应用于哪些领域? RTOS,即实时操作系统(Real-Time Operating System),是一种专门为实时应用程序设计的操作系统,它强调的是对外部事件的快速响应和可预测性。实时系统通常要求在严格的时限内完成关键任务,因此RTOS具备优先级调度、确…...

面试题2:从浏览器输入一个URL,到最终展示前端页面这一过程,会发生什么?

这是一个高频的面试题目。 题目答案是开放性的&#xff0c;一般以后端开发的角度回答。 当地址栏输入一个 URL 后&#xff1a; 一、首先会进行 DNS 域名解析 DNS 域名解析&#xff1a;网络上的设备都是通过 IP 地址&#xff0c;作为身份标识的。但是由于点分十进制的 IP 地址 …...

<Rust><iced><resvg>基于rust使用iced构建GUI实例:使用resvg库实现svg转png

前言 本文是使用rust库resvg来将svg图片转为png图片。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;resvg 代码分析 resvg是一个基于rust的svg渲染库&#xff0c;其官方地址&#xff1a; An SVG rendering li…...

面试突击:Java 中的泛型

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。今天想和大家聊聊 Java 中的泛型。 什么是泛型&#xff1f; Java 泛型&#xff08;Generics&#xff09; 是 JDK 5…...

3_2、MFC常用控件用法:组合框、滚动条和图片控件

MFC控件用法 1、组合框1.1 简介1.2 创建CComboBox类的主要成员函数 1.3 实例 2、滚动条控件2.1 简介2.2 创建CScrollBar类的主要成员函数 2.3 实例 3、图片控件3.1 简介3.2 创建图片控件静态加载图片图片控件动态加载图片 1、组合框 1.1 简介 组合框其实就是把一个编辑框和一…...

如何使用gprof对程序进行性能分析

如何使用gprof对程序进行性能分析 目录 1 gprof概述 2 gprof原理简述 3 gprof使用 3.1 gprof使用简述 3.2 gprof使用示例 4 小结 1 gprof概述 gprof 是 一个 GNU 的程序性能分析工具&#xff0c;可以用于分析C\C程序的执行性能。gprof工具可以统计出各个函数的调用次数、执…...

四川汇聚荣科技有限公司靠谱吗?

在如今这个信息爆炸的时代&#xff0c;了解一家公司是否靠谱对于消费者和合作伙伴来说至关重要。四川汇聚荣科技有限公司作为一家位于中国西部地区的企业&#xff0c;自然也受到了人们的关注。那么&#xff0c;这家公司究竟如何呢?接下来&#xff0c;我们将从多个角度进行深入…...

可灵王炸更新,图生视频、视频续写,最长可达3分钟!Runway 不香了 ...

现在视频大模型有多卷&#xff1f; Runway 刚在6月17号 发布Gen3 &#xff0c;坐上王座没几天&#xff1b; 可灵就在6月21日中午&#xff0c;重新夺回了王座&#xff01;发布了图生视频功能&#xff0c;视频续写功能&#xff01; 一张图概括&#xff1a; 二师兄和团队老师第一…...

从‘量子电子商务’到三方协议:手把手拆解量子数字签名(QDS)的核心流程与实验挑战

量子数字签名&#xff1a;从理论到实验的技术深潜与挑战解析 量子数字签名&#xff08;QDS&#xff09;作为后量子密码学的重要分支&#xff0c;正在从实验室走向实际应用。不同于传统数字签名依赖数学难题的复杂性&#xff0c;QDS基于量子力学的基本原理&#xff0c;为信息安全…...

3分钟掌握AI工作流:Awesome-Dify-Workflow全功能实战指南

3分钟掌握AI工作流&#xff1a;Awesome-Dify-Workflow全功能实战指南 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程&#xff0c;自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awesome-Di…...

flutter_staggered_grid_view性能优化:解决大数据量网格渲染卡顿问题

flutter_staggered_grid_view性能优化&#xff1a;解决大数据量网格渲染卡顿问题 【免费下载链接】flutter_staggered_grid_view A Flutter staggered grid view 项目地址: https://gitcode.com/gh_mirrors/fl/flutter_staggered_grid_view flutter_staggered_grid_view…...

演员-评论家网络在ADP中的应用:如何构建和训练你的第一个模型

演员-评论家网络在自适应动态规划中的实战指南 当我们需要解决复杂控制问题时&#xff0c;传统动态规划方法往往面临"维度灾难"的困境。演员-评论家网络&#xff08;Actor-Critic Network&#xff09;作为自适应动态规划&#xff08;ADP&#xff09;的核心架构&#…...

all-MiniLM-L6-v2部署教程:Ollama中自定义embedding模型名称与API端点配置

all-MiniLM-L6-v2部署教程&#xff1a;Ollama中自定义embedding模型名称与API端点配置 想在你的本地环境中快速部署一个轻量、高效的文本向量化服务吗&#xff1f;all-MiniLM-L6-v2是一个绝佳的选择。这个模型虽然小巧&#xff0c;但在语义理解任务上表现不俗&#xff0c;特别…...

突破Windows 7系统限制:Python 3.9+版本的创新兼容方案

突破Windows 7系统限制&#xff1a;Python 3.9版本的创新兼容方案 【免费下载链接】PythonVista Python 3.9 installers that support Windows 7 SP1 and Windows Server 2008 R2 项目地址: https://gitcode.com/gh_mirrors/py/PythonVista 一、经典系统的现代Python支持…...

AI超分辨率技术突破:OptiScaler实现跨显卡自由体验

AI超分辨率技术突破&#xff1a;OptiScaler实现跨显卡自由体验 【免费下载链接】OptiScaler DLSS replacement for AMD/Intel/Nvidia cards with multiple upscalers (XeSS/FSR2/DLSS) 项目地址: https://gitcode.com/GitHub_Trending/op/OptiScaler 你的显卡是否因厂商…...

【C++:红黑树】4 条规则深度理解红黑树:从原理、变色、旋转到完整实现代码

&#x1f525;小叶-duck&#xff1a;个人主页 ❄️个人专栏&#xff1a;《Data-Structure-Learning》《C入门到进阶&自我学习过程记录》 《算法题讲解指南》--优选算法 《算法题讲解指南》--递归、搜索与回溯算法 《算法题讲解指南》--动态规划算法 ✨未择之路&#xff0…...

AI漫剧软件2025推荐,助力漫画创作高效产出

AI漫剧软件2025推荐&#xff0c;助力漫画创作高效产出在当今数字化时代&#xff0c;AI漫剧软件市场正蓬勃发展。据中国动漫协会《2025中国动漫产业发展报告》显示&#xff0c;2025年AI漫剧软件市场规模同比增长了45%&#xff0c;越来越多的创作者开始借助此类软件提升创作效率。…...

大数据环境下数据仓库的自动化运维实践

大数据环境下数据仓库的自动化运维实践 关键词:大数据、数据仓库、自动化运维、实践、效率提升 摘要:本文围绕大数据环境下数据仓库的自动化运维实践展开。首先介绍了大数据环境和数据仓库自动化运维的背景知识,接着详细解释了相关核心概念及其关系,阐述了自动化运维的核心…...