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

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

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

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

join( )

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

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

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

示例代码如下:

cpp 复制代码
#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界面线程可以剥离到后台

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

cpp 复制代码
// 线程函数
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对象是否可以被join。joinable方法返回一个bool值,如果线程可以被join,则返回true,否则返回false。

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

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

C++ 复制代码
#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";
        // 可以安全地调用 join
        myThread.join();
    } else {
        std::cout << "Thread is not joinable\n";
    }

    std::cout << "Main Function\n";

    return 0;
}
相关推荐
晨曦中的暮雨9 分钟前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
喵了几个咪43 分钟前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
程序员清风1 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
学长毕设1 小时前
基于SpringBoot的青少年编程学习平台系统-附源码
spring boot·学习·青少年编程
在世修行2 小时前
智学文枢:页面切换与跨页数据预填
python·桌面应用·signal·1024程序员节·pyside·跨页跳转·状态预填
2601_962885723 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
打工仔折腾 AI3 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
choumin3 小时前
C++中万能引用与std::forward的作用和用法
c++·万能引用·std forward
Wang's Blog3 小时前
Java 项目实战: 交友项目 - 圈子功能实现:总结
java·开发语言·交友
信誓旦旦的程序猿4 小时前
【Python量化实战宝典 #21】北向资金跟随手册:聪明钱择时信号(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口