C++ C++;11:如果你不';t为std::thread调用join()
如下所示:C++ C++;11:如果你不';t为std::thread调用join(),c++,multithreading,c++11,stdthread,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; } main将在5秒后退出,仍在执行的th1会发生什么情
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;
}
main
将在5秒后退出,仍在执行的th1
会发生什么情况
即使您在main
中定义的th1
线程对象超出范围并被销毁,它是否仍会继续执行直到完成
th1
是在它完成执行后还是在程序终止时以某种方式被清除
如果线程是在函数中创建的,而不是在main
中创建的,那么在程序终止或函数超出范围之前,线程是否一直存在
如果希望线程上出现某种类型的超时行为,那么不调用线程的join
安全吗?std::thread::~thread()
如果*它有一个关联的线程(joinable()==true
),则调用std::terminate()
)
资料来源:
这意味着像这样的程序根本就不是格式良好或安全的
但是请注意,在本例中,boost::thread::~thread()
调用detach()
。
(正如用户dyp在注释中所述,这种行为在较新的版本中被弃用)
你可以用RAII解决这个问题。只需将线程包装在另一个类中,该类在销毁时将具有所需的行为。如果调用析构函数时未分离或加入线程,它将调用
std::terminate
,我们可以通过转到“我们看到”部分30.3.1.3
线程析构函数说明:
如果joinable(),则调用std::terminate()。否则,就没有效果。[
注意:在中隐式分离或连接可接合()线程
它的析构函数可能导致难以调试正确性(例如
仅当
引发异常。因此程序员必须确保
当线程仍然可连接时,析构函数永远不会执行。-结束
注]
关于这种行为的基本原理,我们可以在
为什么可连接线程的析构函数必须调用
终止?毕竟,析构函数可以与子函数连接
线程,或者它可以从子线程分离,或者它可以取消
线。简而言之,您不能像这样加入析构函数
导致意外(代码中未明确指示)程序
冻结以防f2抛出
下面是一个例子,它还说:
您不能分离,因为这可能会导致主线程
保留启动子线程的作用域,以及子线程
线程保持运行并保持对已存在的作用域的引用
走了
这篇文章引用了一个反对先前建议的论点,即如果可连接,则在销毁时分离,并指出两个备选方案之一是连接,这可能会导致死锁。另一个备选方案是我们今天使用的,即
std::terminate
如果可连接,则在销毁时终止。在C++11中,当新创建的线程超出作用域时(调用我们的it dtor),必须显式指定“发生了什么”。有时,当我们确信主线程正在继续,并且我们的线程充当“管道”时,可以安全地将它们“分离()”;有时,当我们等待工作线程完成其操作时,我们会“join()”它们
如前所述,程序员必须确保当线程仍然可连接时,不会执行析构函数
指定多线程策略。在本例中,调用了
std::terminate()
。为什么不试试?@Drop,因为这不是了解担保的可靠方法。@dyp询问Stackoverflow也不是。通过编译和运行这个5行的示例,他至少可以找到一条线索。保证只有一个来源——标准。@Drop“对Stackoverflow的询问都不是”好的,所以在我看来,答案引用了一个可靠的来源(正如您所做的)。然而,即使是标准本身也不是一个完全可靠的来源,因为它包含缺陷。编译器提供程序通常会偏离字面解释,例如合并缺陷报告的建议解决方案。由于存在未定义的行为,我认为通过尝试来了解担保是不好的做法。我认为“你为什么不尝试一下?”是一个非常有效的回答,如果它表明OP在提问之前费心运行一些实验,那么问题就会得到改善。“我试过了,我的程序被终止了,这是意料之中的吗?”这是一个比“如果我这么做会发生什么?”更好的问题。这不像我们谈论的是吃一些野生的未知浆果,C++11编译器是免费的,运行实验很容易,也很有教育意义。boost的这种行为不受欢迎:@dyp Cool!我可以在我的回答中加上吗?;)“或者它可以取消线程…”“取消”std::线程是什么意思?顺便说一句,值得注意的是,C++20添加了jthread,它在销毁时加入。