C++ 当main()退出时,分离的线程会发生什么情况?

C++ 当main()退出时,分离的线程会发生什么情况?,c++,multithreading,c++11,exit,stdthread,C++,Multithreading,C++11,Exit,Stdthread,假设我正在启动一个std::thread然后detach() 进一步假设程序没有连接分离线程1的可靠协议,因此当退出main()时,分离线程仍然运行 我在标准中找不到任何东西(更准确地说,在N3797 C++14草案中),它描述了应该发生的事情,1.10和30.3都没有相关的措辞 1另一个可能相当的问题是:“分离的线程是否可以再次连接”,因为无论您发明了什么协议来连接,都必须在线程仍在运行时执行信令部分,操作系统调度器可能会在执行信号发送后决定让线程休眠一个小时,而接收端无法可靠地检测到线程实际

假设我正在启动一个
std::thread
然后
detach()

进一步假设程序没有连接分离线程1的可靠协议,因此当退出
main()
时,分离线程仍然运行

我在标准中找不到任何东西(更准确地说,在N3797 C++14草案中),它描述了应该发生的事情,1.10和30.3都没有相关的措辞

1另一个可能相当的问题是:“分离的线程是否可以再次连接”,因为无论您发明了什么协议来连接,都必须在线程仍在运行时执行信令部分,操作系统调度器可能会在执行信号发送后决定让线程休眠一个小时,而接收端无法可靠地检测到线程实际已完成

如果在运行分离线程的情况下耗尽
main()
是未定义的行为,则使用
std::thread::detach()
是未定义的行为,除非主线程从未退出2

因此,在运行分离线程的情况下运行
main()
,必须具有定义的效果。问题是:(C++的标准,而不是POSIX,不是OS文档,……)是那些定义的影响。
2无法连接分离的线程(在
std::thread::join()
的意义上)。您可以等待分离线程的结果(例如,通过future from
std::packaged_task
,或通过计数信号量或标志和条件变量),但这并不保证线程已完成执行。实际上,除非将信令部分放入线程的第一个自动对象的析构函数中,否则通常会有在信令代码之后运行的代码(析构函数)。如果操作系统计划主线程使用结果并在分离的线程运行完所述析构函数之前退出,那么会发生什么?

程序退出后线程的命运是未定义的行为。但现代操作系统会在关闭进程时清除进程创建的所有线程

分离
std::thread
时,这三个条件将继续保持:

  • *此
    不再拥有任何线程
  • joinable()
    将始终等于
    false
  • get_id()
    将等于
    std::thread::id()
  • 拆线 根据:

    将执行线程与线程对象分离,允许 独立执行。任何分配的资源都将被删除 线程退出后释放

    发件人:

    pthread_detach()函数应向实现指示 该线程的存储可以在该线程运行时回收 终止。如果线程尚未终止,则pthread_detach()将不会终止 使其终止。多个pthread_detach()调用的效果 未指定同一目标线程上的

    分离线程主要是为了节省资源,以防应用程序不需要等待线程完成(例如守护进程,它必须运行到进程终止):

  • 释放应用程序端句柄:可以让对象在不加入的情况下离开作用域,这通常会导致在销毁时调用
  • 允许操作系统在线程退出时自动清理特定于线程的资源(),因为我们明确指定,我们对以后加入线程不感兴趣,因此不能加入已经分离的线程
  • 杀线 进程终止的行为与主线程的行为相同,至少可以捕获一些信号。其他线程是否可以处理信号并不重要,因为可以在主线程的信号处理程序调用中连接或终止其他线程。)

    如前所述。可以通过发出信号、调用
    exit()
    或从主函数返回来终止进程本身。然而,C++11不能也没有试图定义底层操作系统的确切行为,而Java虚拟机的开发人员肯定可以在某种程度上抽象出这些差异。另外,奇特的进程和线程模型通常出现在古老的平台(C++11可能不会移植到这些平台)和各种嵌入式系统上,这些平台可能有特殊和/或有限的语言库实现,也可能有有限的语言支持

    螺纹支架 如果不支持线程,则应返回无效id(默认构造的
    std::thread::id
    ),因为存在一个普通进程,该进程不需要运行thread对象,而线程的构造函数应抛出。这就是我对C++11和当今操作系统的理解。如果有一个支持线程的操作系统,它的进程中没有生成主线程,请告诉我

    控制线程
    如果需要保持对线程的控制以正确关闭,可以通过使用同步原语和/或某种标志来实现。但是,在这种情况下,我更喜欢先设置一个shutdown标志,然后再设置一个join,因为分离线程并没有增加复杂性的意义,因为资源将同时被释放,对象的几个字节与更高的复杂度和可能更多的同步原语相比应该是可以接受的。

    原始问题“当
    main()
    退出时分离的线程会发生什么情况”的答案是:

    它继续运行(因为标准没有说它已停止),这是定义良好的,只要它既不涉及其他线程的(自动|线程_局部)变量,也不涉及静态对象

    这似乎是允许线程管理器作为静态对象的(注意,[basic.start.term]/4中也这么说,t
    #include <iostream>
    #include <string>
    #include <thread>
    #include <chrono>
    
    void thread_fn() {
      std::this_thread::sleep_for (std::chrono::seconds(1)); 
      std::cout << "Inside thread function\n";   
    }
    
    int main()
    {
        std::thread t1(thread_fn);
        t1.detach();
    
        return 0; 
    }