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

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

  • 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对象是否可以被joinjoinable方法返回一个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;
}
相关推荐
淮北49410 小时前
windows安装minicoda
windows·python·conda
Evand J11 小时前
【MATLAB例程】基于USBL和DVL的线性回归误差补偿,对USBL和DVL导航数据进行相互补偿,提高定位精度,附代码下载链接
开发语言·matlab·线性回归·水下定位·usbl·dvl
Larry_Yanan11 小时前
QML学习笔记(四十二)QML的MessageDialog
c++·笔记·qt·学习·ui
爱喝白开水a11 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱
Neverfadeaway12 小时前
【C语言】深入理解函数指针数组应用(4)
c语言·开发语言·算法·回调函数·转移表·c语言实现计算器
武子康12 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
杰克尼12 小时前
JavaWeb_p165部门管理
java·开发语言·前端
R-G-B12 小时前
【35】MFC入门到精通——MFC运行 不显示对话框 MFC界面不显示
c++·mfc·mfc运行 不显界面·mfc界面不显示
能不能别报错12 小时前
K8s学习笔记(十九) K8s资源限制
笔记·学习·kubernetes
一成码农12 小时前
JavaSE面向对象(下)
java·开发语言