为什么在销毁线程之前必须先调用join()或detach()?

Mos*_*aev 31 c++ multithreading

我不明白为什么当std::thread销毁销毁时它必须处于join()或detach()状态。

联接等待线程完成,而分离则没有。似乎有些中间状态我不了解。因为我的理解是join和detach是互补的:如果不调用join(),则默认为detach()。

这样说,假设您正在编写一个创建线程的程序,并且仅在此线程的生命周期后期才调用join(),所以直到您调用join为止,该线程基本上像分离的线程一样在运行,没有?

从逻辑上讲,detach()应该是线程的默认行为,因为这是线程的定义,它们与其他线程无关地并行执行。

那么,当线程对象被破坏时,为什么要调用Terminate()?为什么标准不能简单地将线程视为已分离?

我不了解在销毁线程之前未调用join()或detached()时终止程序的原因。这样做的目的是什么?

更新:

我最近遇到了这个。安东尼·威廉姆斯(Anthony Williams)在他的《并发中的行动》一书中指出:“ C ++ 17的建议之一是为join_thread类提供类似于std :: thread的要求,只是它会像scoped_thread一样自动加入析构函数中。这在委员会中没有达成共识,因此未被标准接受(尽管对于C ++ 20来说,它仍然可以按std :: jthread的标准进行...)”

fif*_*ifo 37

从技术上讲,答案是“因为规范如此规定”,但这是一个晦涩的答案。我们无法理解设计师的想法,但是以下一些问题可能是造成这些问题的原因:

使用POSIX pthread,子线程必须在退出后再加入,否则子线程将继续占用系统资源(例如内核中的进程表条目)。这是通过完成的pthread_join()。如果进程对子线程持有一个HANDLE,则Windows有一个类似的问题。尽管Windows不需要完全连接,但是该进程仍必须调用CloseHandle()以在线程上释放其refcount。

由于std::thread是跨平台的抽象,因此受到需要连接的POSIX要求的约束。

从理论上讲,std::thread析构函数可以调用pthread_join()而不是引发异常,但这(主观上)可能增加死锁的风险。而正确编写的程序将知道何时在安全时间插入连接。

也可以看看:


Chr*_*odd 15

您会感到困惑,因为您正在将std::thread对象与其所引用的执行线程相混淆。甲std::thread对象是一个C ++对象(一堆存储器字节)充当到执行的线程的参考。当您调用时std::thread::detach,发生的事情是该std::thread对象与执行线程“分离”了-它不再引用(任何)执行线程,并且执行线程继续独立运行。但是std::thread对象仍然存在,直到被销毁为止。

执行线程完成后,它将其退出信息存储到std::thread引用它的对象中,如果有一个(如果是分离的,则没有一个,因此退出信息将被丢弃。)它没有对std::thread对象的其他影响-特别是该std::thread对象不会被销毁,并且会继续存在,直到有人销毁它为止。

  • @MosheRabaev迫使您考虑并决定如何处理线程的末尾。 (4认同)