C++ 11:如果你没有为std :: thread调用join()会发生什么

kik*_*iki 29 c++ multithreading c++11 stdthread

给出如下:

void test() 
{
  std::chrono::seconds dura( 20 );
  std::this_thread::sleep_for( dura );
}

int main()
{
  std::thread th1(test);
  std::chrono::seconds dura( 5 );
  std::this_thread::sleep_for( dura );
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

main将在5秒后退出,那还会发生什么th1

即使th1您定义的线程对象main超出范围并被销毁,它是否会继续执行直到完成?

th1完成执行后是否只是坐在那里或在程序终止时以某种方式清理?

如果线程是在函数中创建的,那么main- 在程序终止或函数超出范围之前,线程是否保持不变?

join如果你想在线程上有某种类型的超时行为,那么简单地不调用线程是否安全?

Sha*_*our 20

如果在调用析构函数时你没有分离或加入一个线程,它将调用std::terminate,我们可以通过转到草案C++ 11标准看到这一点,我们看到该节30.3.1.3 线程析构函数说:

如果是joinable(),则调用std :: terminate().否则,没有任何影响.[注意:在析构函数中隐式分离或连接joinable()线程可能导致难以调试正确性(用于分离)或性能(用于连接)仅在引发异常时遇到错误.因此,程序员必须确保在线程仍可连接时永远不会执行析构函数. - 尾注]

至于这种行为的基本原理,我们可以使用std :: thread(Not)中找到一个很好的总结

为什么可连接线程的析构函数必须调用std :: terminate?毕竟,析构函数可以与子线程连接,或者它可以从子线程分离,或者它可以取消线程.简而言之,你不能加入析构函数,因为这会导致意外(在代码中没有明确指出)程序冻结,以防f2抛出.

以下是一个例子,并说:

你不能分离,因为它会冒着主线程离开子线程被启动的范围的风险,并且子线程继续运行并保持对已经消失的范围的引用.

文章引用了N2802:重新考虑对线程对象的破坏分离的请求,这是对先前提议的论证,如果可连接则分解为破坏,并且它指出两个替代方案中的一个将是加入,这可能导致死锁另一种选择是我们今天所拥有的std::terminate,如果可以加入就会破坏.


Iva*_*rop 5

std::thread::~thread()

如果*这有一个关联的线程(joinable() == true),std::terminate()则调用

资料来源:http://en.cppreference.com/w/cpp/thread/thread/~thread

这意味着像这样的程序根本没有格式或安全.

但请注意,在这种情况下boost::thread::~thread()调用detach().(正如用户dyp在注释中所述,在最近的版本中不推荐使用此行为)

您可以随时使用RAII解决此问题.只需将您的线程包装在另一个类中,该类将在销毁时具有所需的行为.

  • 不推荐使用boost的行为:http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#thread.thread_management.thread.destructor (3认同)