【问题标题】:std::thread created as detach thread terminates when main exits [duplicate]当主退出时,作为分离线程创建的std :: thread终止[重复]
【发布时间】:2021-10-11 22:12:03
【问题描述】:

我正在编写以下 C++ 代码来创建分离线程:

void threadF() {
    ofstream        f("data") ;
    for(int i=1; i<=5; i++) {
            f<<"t1:::"<<i<<"\n" ;
            f.flush() ;
            sleep(1) ;
    }
    f.close() ;
}

int main() {

    thread t1(threadF) ;

    cout<<"main #1\n" ;
    sleep(2) ;
    t1.detach() ;
    cout<<"main #2\n" ;
}

当我运行这段代码时,我有以下观察结果:

  1. 2 秒后主退出(如预期)
  2. 分离子线程似乎也只运行了 2 秒,因为输出 data 文件仅包含 2 行。

我预计线程应该已经完全执行,并且输出 data 文件应该包含 5 行。这没有发生

我需要对此行为作出解释。

根据墨水What happens to a detached thread when main() exits?,这是否意味着分离的线程会在主线程退出时自动终止?

【问题讨论】:

  • 如果你想等待线程完成,join()它。
  • main返回结束进程,它杀死所有正在运行的线程。使用detatch 通常是一个错误。你不知道线程会在什么时候死掉。它可能会在写入文件时死掉,并且(取决于操作系统和文件系统)它可能会使其处于损坏状态。
  • 这并不能解决问题,但您无需致电f.close() ;。析构函数会这样做。
  • '使用 detatch 通常是一个错误' nope.

标签: c++ multithreading


【解决方案1】:

我需要对此行为作出解释。

main 返回时,进程终止。如果有线程正在运行,则无法保证它有机会完成。

此外,从技术上讲,在main 返回后触及任何全局状态都会导致未定义的行为,因为所有静态存储对象都将被主线程销毁。

基本上,std::thread::detach 很少有用,因为您只需要使用其他方式来加入线程即可。没有“等待所有分离的线程然后停止”的标准方法。不过有一些特定于平台的方法 (pthread_exit)。

【讨论】:

  • thread::detach 在您想要某种其他编程语言称为“守护线程”的有限情况下很有用。也就是说,一个长时间运行的线程,它在正在运行的程序中执行一些服务,但它修改任何持久状态,因此当它突然终止时不会造成任何永久性伤害。一个例子可能是管理某种内存数据缓存的线程。 François Andrieux 说detach 通常是一个错误。我会称之为“代码异味”——这是在代码审查中进行额外审查的原因。
  • 我在过去 30 年中使用的每个线程都是独立运行的,没有加入。反模式是持续创建/终止/加入。应用程序生命周期和池线程都很好。创建/加入应该是最后的手段。
  • @MartinJames,“创建/加入”不必是连续的。有一些用例可以让主线程join 在进程终止之前成为一个长时间运行的“后台”线程。 (例如,如果后台线程更新了一些持久性资源。)OTOH,任何想要设计一个以这种方式运行的新程序的人都可能希望在开始之前对crash-only software 的主题进行一些阅读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-07
  • 2012-08-06
相关资源
最近更新 更多