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

【C++多线程编程】(五)之 线程生命周期管理join() 与 detach()

在C++中,std::thread 类用于创建和管理线程。std::thread 提供了两种主要的方法来控制线程的生命周期:joindetach

  • detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不等待新线程结束。
  • join方式,等待启动的线程完成,才会继续往下执行。

需要注意的是,一旦线程被分离,就无法再对其调用 join 方法,否则会导致程序终止。因此,在使用 detach 方法时,需要确保主线程不再依赖于被分离的线程的执行。

join( )

  • join 方法用于等待一个线程的完成。当一个线程调用另一个线程的 join 方法时,调用线程将被阻塞,直到被调用的线程执行完成。这样做的主要目的是确保主线程等待所有其他线程完成后再继续执行。

  • 使用 join 的主要目的是确保在主线程继续执行之前,所有其他线程都已经完成。这种阻塞行为是为了协调不同线程之间的执行顺序,以避免并发问题或确保线程的执行顺序符合程序的逻辑。

  • 当然,要注意使用 join 时可能引入的潜在问题,比如死锁(如果两个线程相互等待对方完成),因此在使用 join 时需要仔细考虑线程之间的交互。

示例代码如下:

#include <iostream>
#include <thread>void myFunction() {// 线程执行的代码std::cout << "Thread Function\n";
}int main() {std::thread myThread(myFunction);// 主线程等待 myThread 执行完成myThread.join();std::cout << "Main Function\n";return 0;
}

在上面的例子中,main 函数中的线程通过 join 方法等待 myThread 的执行完成。

join后面的代码不会被执行,除非子线程结束。

detach( )

detach()std::thread 类的一个成员函数,用于将线程与主线程分离。当调用 detach() 后,主线程不再等待被分离的线程执行完成,而是让它在后台运行。

下面是 detach() 的一些关键点:

  1. 分离线程: 调用 detach() 后,当前线程对象所代表的线程就被分离了。这意味着主线程不再对该线程进行管理,不再等待它的完成。

  2. 后台运行: 被分离的线程将在后台运行,即使主线程退出,被分离的线程仍然可以继续执行。

  3. 资源回收: 当被分离的线程运行结束时,其资源(如线程的栈空间等)会被自动释放,不需要手动调用 join() 来等待线程结束。线程的资源将由操作系统自动回收。

  4. 潜在问题: 使用 detach() 带来的便利性是,主线程可以继续执行其他任务而不必等待被分离的线程完成。然而,这也引入了一些潜在的问题,比如可能导致资源泄漏、难以追踪线程的状态等。

    在实际应用中,除非你确切地知道你需要分离线程,并且明白潜在的问题,否则最好使用 join() 等待线程的完成,以避免可能的资源泄漏和其他难以调试的问题。

如:典型UI界面线程可以剥离到后台

如果主线程运行结束,程序则结束

// 线程函数
void myThreadFunc(int n) {}int main()
{// 创建并启动一个线程std::thread myThread(myThreadFunc, 5);myThread.detach();// 主线程继续执行其他任务std::cout << "Hello from the main thread!" << std::endl;// 注意:不再调用 join(),因为线程已被分离return 0;
}

判断线程是否被join( )

在C++中,可以使用joinable方法来检查一个std::thread对象是否可以被joinjoinable方法返回一个bool值,如果线程可以被join,则返回true,否则返回false

在这个例子中,首先创建了一个线程myThread,然后通过joinable方法检查该线程是否可以被join。如果线程是joinable的,就安全地调用了join方法。这是为了防止在不安全的状态下调用join,因为一旦线程被分离,就无法再调用join

总之,使用joinable可以在调用join之前检查线程的状态,以确保线程在调用join时处于正确的可合并状态。

#include <iostream>
#include <thread>void myFunction() {// 线程执行的代码std::cout << "Thread Function\n";
}int main() {std::thread myThread(myFunction);if (myThread.joinable()) {std::cout << "Thread is joinable\n";// 可以安全地调用 joinmyThread.join();} else {std::cout << "Thread is not joinable\n";}std::cout << "Main Function\n";return 0;
}

相关文章:

【C++多线程编程】(五)之 线程生命周期管理join() 与 detach()

在C中&#xff0c;std::thread 类用于创建和管理线程。std::thread 提供了两种主要的方法来控制线程的生命周期&#xff1a;join 和 detach。 detach方式&#xff0c;启动的线程自主在后台运行&#xff0c;当前的代码继续往下执行&#xff0c;不等待新线程结束。join方式&…...

金融信贷场景的风险“要素”与主要“风险点”

目录 要素一:贷款对象 风险点1:为不具备主体资格或主体资格有瑕疵的借款人发放贷款 风险表现: 防控措施: 风险点2:向国家限控行业发放贷款 风险表现: 防控措施: 风险点3:受理不符合准入条件的客户申请 风险表现: 防控措施: 要素二:金额 风险点4:过渡授…...

ubuntu下docker安装,配置python运行环境

参考自: 1.最详细ubuntu安装docker教程 2.使用docker搭建python环境 首先假设已经安装了docker&#xff0c;卸载原来的docker 在命令行中运行&#xff1a; sudo apt-get updatesudo apt-get remove docker docker-engine docker.io containerd runc 安装docker依赖 apt-get…...

在Docker中安装kafka遇到问题记录

命令含义解答&#xff1a; 在docker安装kafka的时候&#xff0c;启动kafka的时候会执行下面语句&#xff1a; docker run -d --log-driver json-file --log-opt max-size100m --log-opt max-file2 --name kafka -p 9092:9092 -e KAFKA_BROKER_ID0 -e KAFKA_ZOOKEEPER_CONNEC…...

aws-waf-cdn 基于规则组的永黑解决方案

1. 新建waf 规则组 2. 为规则组添加规则 根据需求创建不同的规则 3. waf中附加规则组 &#xff08;此时规则组所有规则都会附加到waf中&#xff0c;但是不会永黑&#xff09; 此刻&#xff0c;可以选择测试下规则是否生效&#xff0c;测试前确认保护资源绑定无误 4. 创建堆…...

如何实现免费无限流量云同步笔记软件Obsidian?

目录 前言 如何实现免费无限流量云同步笔记软件Obsidian&#xff1f; 一、简介 软件特色演示&#xff1a; 二、使用免费群晖虚拟机搭建群晖Synology Drive服务&#xff0c;实现局域网同步 1 安装并设置Synology Drive套件 2 局域网内同步文件测试 三、内网穿透群晖Synol…...

GPTs | Actions应用案例

上篇文章说道&#xff0c;如何使用创建的GPTs通过API接口去获取外部的一些信息&#xff0c;然后把获取的外部信息返回给ChatGPT让它加工出来&#xff0c;回答你的问题&#xff0c;今天我们就来做一个通俗易懂的小案例&#xff0c;让大家来初步了解一下它的使用法&#xff01; …...

Python Opencv实践 - 手势音量控制

本文基于前面的手部跟踪功能做一个手势音量控制功能&#xff0c;代码用到了前面手部跟踪封装的HandDetector.这篇文章在这里&#xff1a; Python Opencv实践 - 手部跟踪-CSDN博客文章浏览阅读626次&#xff0c;点赞11次&#xff0c;收藏7次。使用mediapipe库做手部的实时跟踪&…...

关于Selenium的网页对象单元测试的设计模式

写在前面&#xff1a;经过了实践总结一下经验&#xff0c;心得进行一个分享。 首先driver是可以单独抽出来的&#xff0c;变成一个driver函数放在driver.py。 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver…...

基于多反应堆的高并发服务器【C/C++/Reactor】(上)

&#xff08;一&#xff09;初始化服务器端用于监听的套接字 Server.h #pragma once // 初始化监听的套接字 int initListenFd(unsigned short port); Server.c int initListenFd(unsigned short port) {// 1.创建监听的fdint lfd socket(AF_INET, SOCK_STREAM, 0);if(lf…...

腾讯云debian服务器的连接与初始化

目录 1. 远程连接2. 软件下载3. 设置开机自启动 1. 远程连接 腾讯云给的服务器在安装好系统之后&#xff0c;只需要在防火墙里面添加一个白名单&#xff08;ip 或者域名&#xff09;就能访问了。 浏览器打开https://www.ipip.net/&#xff0c;在左下角找到自己所用的WIFI的公…...

医保购药小程序:智能合约引领医疗数字革新

在医疗领域&#xff0c;医保购药小程序通过引入智能合约技术&#xff0c;为用户提供更为高效、安全的购药体验。本文将通过简单的智能合约代码示例&#xff0c;深入探讨医保购药小程序如何利用区块链技术中的智能合约&#xff0c;实现医保结算、购药监控等功能&#xff0c;为医…...

神经网络:深度学习优化方法

1.有哪些方法能提升CNN模型的泛化能力 采集更多数据&#xff1a;数据决定算法的上限。 优化数据分布&#xff1a;数据类别均衡。 选用合适的目标函数。 设计合适的网络结构。 数据增强。 权值正则化。 使用合适的优化器等。 2.BN层面试高频问题大汇总 BN层解决了什么问…...

Unity中Shader旋转矩阵(二维旋转矩阵)

文章目录 前言一、旋转矩阵的原理1、我们以原点为中心&#xff0c;旋转坐标轴θ度2、求 P~2x~&#xff1a;3、求P~2y~:4、最后得到 P~2~点 的点阵5、该点阵可以拆分为以下两个矩阵相乘的结果 二、在Shader中&#xff0c;使用该旋转矩阵实现围绕 z 轴旋转1、在属性面板定义 floa…...

前端面试题(计算机网络):options请求方法及使用场景

OPTIONS请求方法及使用场景 回答思路&#xff1a;什么是options请求-->options请求方法-->options使用场景什么是options请求&#xff1f;&#xff08;浅入&#xff09;扩展&#xff1a;常见的HTTP请求有什么&#xff1f;扩展&#xff1a;常见的HTTP请求的作用&#xff1…...

使用docker-compose管理docker服务

使用docker-compose管理docker服务 1&#xff0c;创建docker-compose.yml version: 3 services:javaapp:build: context: ./javaappdockerfile: Dockerfileports:- "9202:9202"- "19202:19202"goapp:build: context: ./goappdockerfile: Dockerfileports…...

Python_Tkinter和OpenCV模拟行星凌日传输光度测定

传输光度测定 在天文学中&#xff0c;当相对较小的天体直接经过较大天体的圆盘和观察者之间时&#xff0c;就会发生凌日。 当小物体移过较大物体的表面时&#xff0c;较大物体会稍微变暗。 最著名的凌日是水星和金星对太阳的凌日。 借助当今的技术&#xff0c;天文学家可以在…...

【安全】使用auparse解析auditd审计日志

使用auparse解析auditd审计日志 1 审计日志特点 查看auditd.log的日志&#xff0c;审计日志的格式如下&#xff1a; typeSYSCALL msgaudit(1703148319.954:11680975): archc000003e syscall2 successyes exit5 a01102430 a10 a21b6 a324 items1 ppid7752 pid7761 auid0 uid0…...

flink watermark 实例分析

WATERMARK 定义了表的事件时间属性&#xff0c;其形式为: WATERMARK FOR rowtime_column_name AS watermark_strategy_expression rowtime_column_name 把一个现有的列定义为一个为表标记事件时间的属性。该列的类型必须为 TIMESTAMP(3)/TIMESTAMP_LTZ(3)&#xff0c;且是 sche…...

系列十二(面试)、Java中的GC回收类型有哪些?

一、Java中的GC回收类型 1.1、概述 Java中的GC回收类型主要包含以下几种&#xff0c;即&#xff1a;UseSerialGC、UseParallelGC、UseConcMarkSweepGC、UseParNewGC、UseParallelOldGC、UseG1GC。 1.2、源码...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...