C++ 如果既不调用std::thread::detach也不调用std::thread::join,为什么程序会终止?

C++ 如果既不调用std::thread::detach也不调用std::thread::join,为什么程序会终止?,c++,stdthread,C++,Stdthread,我知道如果既不调用std::thread::detach也不调用std::thread::join。线程对象在析构函数中调用std::terminate。我想知道这个的设计选择是什么?为什么在析构函数中调用std::terminaten。此外,如果它没有在析构函数中调用std::terminate,则不分离的行为与分离现在的行为相同。那么,为什么不在设计线程API时保留thread::join并删除对terminate的调用呢?引擎盖下的考虑因素是什么?掉线不好;几乎在每个平台上,你的程序都会被

我知道如果既不调用
std::thread::detach
也不调用
std::thread::join
。线程对象在析构函数中调用
std::terminate
。我想知道这个的设计选择是什么?为什么在析构函数中调用
std::terminate
n。此外,如果它没有在析构函数中调用
std::terminate
,则不分离的行为与分离现在的行为相同。那么,为什么不在设计线程API时保留
thread::join
并删除对terminate的调用呢?引擎盖下的考虑因素是什么?

掉线不好;几乎在每个平台上,你的程序都会被关闭(我的意思是你会很幸运…)

通过“线程退出时准备就绪”功能,分离的线程不会丢失。但是调用<代码> Debug()/Cube >,而不需要在C++的结尾(代码)>(代码)>之前,将线程的结尾同步,意味着程序的行为可能会被C++标准定义。(大多数线程中的大多数代码都充满了无法在主线程结束后安全运行的代码,因此在
main()
结束后仍处于活动状态的线程不是一个好主意;如果没有连接或等效连接,则无论有多少“睡眠”,线程结束和
main()
之间都存在“竞赛”这种调用的存在通常足以使C++正式注销指定程序的行为。 “我应该分离”的想法是错误的。线程应该默认为
detach()
的想法是疯狂的

默认设置为
join()
detach()更合理
。但是加入可以抛出。抛出析构函数是不好的,因为它们是在抛出过程中进行计算的,如果在抛出过程中涉及到展开的代码依次抛出,则程序终止。此外,如果未经检查,该异常路径可能包含死锁条件,因为您可能会中途退出通过与另一个线程握手,它不知道如何关闭自己

std::thread
不是一个用户友好的安全线程原语;使线程用户友好远远超出了它的范围。用户友好的安全线程原语可以构建在它之上。这是从原始pthread中删除的一步。例如,像IPP之类的库。它所做的是使编写线程代码成为可能在没有平台特定扩展的C++中,

通过在销毁时终止,我们在设计阶段向程序员提供反馈,让他们能够智能地处理问题,而不是忽略问题。这使得线程的使用变得有点困难,但正确使用线程的99.9%的困难不是调用
join()

线程是很难做到正确的。当你出错时,它通常也能正常工作;然后它很少会锁定或崩溃,而且只在其他用户的系统上,符号被去除。一旦你将线程添加到程序中,你就不能依赖“我试过了,它成功了”。你甚至不能依赖于“这段代码在本地是正确的”,因为大多数并发设计都不构成
——三个成对的“正确”子程序在组合时可能会变得不正确


像TBB之类的库,或者你自己的库,可以稍微减少这个问题。不可变状态和函数操作,或者其他一些严格的设计。所有这些最终都涉及到在像
std::thread

这样低级别的东西上编写一个框架。丢失线程是不好的;程序的关闭是不好的wn在几乎每个平台上都变得非常粗糙(我的意思是你可以得到幸运…)

分离线程不能通过“准备就绪退出线程”而丢失,但调用“代码> Debug())/代码>,而不需要在线程的结尾处同步线程的结尾,以在代码>主()/代码>的结尾出现,意味着程序的行为可能会被C++标准定义。(大多数线程中的大多数代码都充满了无法在主线程结束后安全运行的代码,因此在

main()
结束后仍处于活动状态的线程不是一个好主意;如果没有联接或等效项,则线程结束和
main()
之间存在一个“竞赛”,无论有多少“睡眠”“调用你做。这样的种族的存在通常足以使C++正式注销指定你的程序的行为。” “我应该分离”的想法是错误的。线程应该默认为
detach()
的想法是疯狂的

默认设置为
join()
detach()更合理
。但是加入可以抛出。抛出析构函数是不好的,因为它们是在抛出过程中进行计算的,如果在抛出过程中涉及到展开的代码依次抛出,则程序终止。此外,如果未经检查,该异常路径可能包含死锁条件,因为您可能会中途退出通过与另一个线程握手,它不知道如何关闭自己

std::thread
不是一个用户友好的安全线程原语;使线程用户友好远远超出了它的范围。用户友好的安全线程原语可以构建在它之上。这是从原始pthread中删除的一步。例如,像IPP之类的库。它所做的是使编写线程代码成为可能在没有平台特定扩展的C++中,

通过在销毁时终止,我们在设计阶段向程序员提供反馈,让他们能够智能地处理问题,而不是忽略问题。这使得线程的使用变得有点困难,但正确使用线程的99.9%的困难不是调用
join()

穿线
int fib(int n) {
    if (n <= 1) return n;
    int fib1, fib2;
    
    std::thread t([=, &fib1]{fib1 = fib(n-1);});
    fib2 = fib(n-2);
    if (fib2 < 0) throw ...
    t.join();
    return fib1 + fib2;
}
      std::vector<std::pair<unsigned int, unsigned int>> partitions =
        utils::partition_indexes(0, size-1, num_threads);
      std::vector<std::thread> threads;

      LOG(LOG_DEBUG, "controller::reload_all: starting reload threads...");
      for (unsigned int i=0; i<num_threads-1; i++) {
        threads.push_back(std::thread(reloadrangethread(this,
        partitions[i].first, partitions[i].second, size, unattended)));
      }

      LOG(LOG_DEBUG, "controller::reload_all: starting my own reload...");
      this->reload_range(partitions[num_threads-1].first,
        partitions[num_threads-1].second, size, unattended);

      LOG(LOG_DEBUG, "controller::reload_all: joining other threads...");
      for (size_t i=0; i<threads.size(); i++) {
        threads[i].join();
      }