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

2023-12-22 07:20

本文主要是介绍【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()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/523059

相关文章

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Java中如何正确的停掉线程

《Java中如何正确的停掉线程》Java通过interrupt()通知线程停止而非强制,确保线程自主处理中断,避免数据损坏,线程池的shutdown()等待任务完成,shutdownNow()强制中断... 目录为什么不强制停止为什么 Java 不提供强制停止线程的能力呢?如何用interrupt停止线程s

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象