究竟何时是析构函数或终止于调用的线程

Posted

技术标签:

【中文标题】究竟何时是析构函数或终止于调用的线程【英文标题】:When exactly is a destructor or terminate on a thread called 【发布时间】:2019-10-06 06:51:51 【问题描述】:

我正在使用 C++11 std::thread。我的困惑基于以下几点:

如果一个线程上的join()detach() 都没有被调用,则调用该线程上的terminate()。 这意味着当一个线程返回时:

a.它检查是否调用了join()detach(),如果没有,则调用terminate()(产生一个coredump),

b.如果join()被调用,线程的析构函数将被main(或调用线程)调用

c.如果在线程执行时调用了detach() ,线程不会返回主线程进行清理,而是由该线程自己负责调用它自己的析构函数

问题:如果上述几点是正确的,那么我不明白 在哪个确切点是决定终止线程还是不是基于是否调用了join()detach()

void function_1()

        return;

int main()

        std::thread t1(function_1);
        std::cout<<"\nFirst Sleep for 5 seconds:\n"; 
        sleep(5);

        cout<<"\n2nd Sleep for 5 seconds:\n";
        sleep(5);

        if(t1.joinable())
        
                cout<<"\nGonna join()\n";
                t1.detach();
        
        cout<<"Exiting from main ...\n";

由于线程将在第 5 秒之前完成执行,我假设线程应该被终止,因为到目前为止还没有 join()/detach()。但是没有调用terminate()。而是成功分离了一个线程。

但是,如果我不分离,则在 "Exiting from main...." 之后的 2 次睡眠后调用终止,就在 return 0; 之前 这是否意味着线程没有被清理(它的析构函数没有被调用),直到主线程(或被调用的线程)返回?

这就是为什么要detach() 以便线程的清理不必等到主线程(或调用者线程)返回的原因吗?

【问题讨论】:

【参考方案1】:

您似乎混淆了两件事:std::thread 对象,以及该对象管理的执行线程。

std::terminate 的调用由std::thread 对象的析构函数触发如果它是可连接的。这与std::thread对象管理的执行线程是否执行完毕没有直接关系。

在您的代码中,t1 的析构函数将触发std::terminatet1是一个普通的C++对象,这里是main的局部变量。当它的作用域结束时它会被破坏——这里是 main 的结尾。因此,您必须在主返回之前使t1 不可加入,方法是在t1 上调用joindetachfunction_1 是否已完成在其执行线程上的运行无关紧要。

【讨论】:

以上是关于究竟何时是析构函数或终止于调用的线程的主要内容,如果未能解决你的问题,请参考以下文章

c++ 析构函数 是在啥时候执行

C++ 析构函数何时被调用?

C++ 析构函数何时被调用?

9——对象的创建和撤销,构造函数和析构函数

在 MFC 中调用 EndDialog() 时,类析构函数何时触发?

关于析构函数和构造函数何时调用的小例子