有时,如果可连接的std::thread
无法在其析构函数上执行thread::join()
,那么它会很有用。请参阅以下示例。
示例1(错误):
抛出异常后,对象std::thread
已被销毁。一旦流退出作用域,就会在连接发生之前调用析构函数。它使STL显示'abort'的错误消息。
int main( int argc, const char * argv[] )
{
try
{
thread t( [] ()
{
this_thread::sleep_for( chrono::seconds( 1 ) );
cout << "thread done" << endl;
} );
throw exception( "some exception" );
t.join();
}
catch ( const exception & )
{
cout << "exception caught!" << endl;
}
cout << "main done" << endl;
return 0;
}
示例2(正确方法):
在我的try-catch块之前创建了对象t
,并且在try和catch块上都放置了join()。所以它保证了join()的发生。
int main( int argc, const char * argv[] )
{
thread t;
try
{
t = thread( [] ()
{
this_thread::sleep_for( chrono::seconds( 1 ) );
cout << "thread done" << endl;
} );
throw exception( "some exception" );
t.join( );
}
catch ( const exception & )
{
t.join();
cout << "exception caught!" << endl;
}
cout << "main done" << endl;
return 0;
}
......问题是:
连接std::thread
不能自动加入析构函数的原因是什么?
如果它自动发生会更容易。今天完成它的方式要求在try-catch块中使用线程时必须小心,例如......但我确信有人在设计std::thread
时会有这样的想法。所以必须有一个理由......那是什么原因?
PS:我知道我们可以在一个类中包含std::thread
并将join()
放在这个新类的析构函数上......所以它会变成自动的。但这不是重点。我的问题实际上是关于std::thread
本身。
答案 0 :(得分:15)
原因很简单,你不得不考虑它。如果由于异常转义范围而导致std::thread
对象被销毁,则连接可能会在堆栈展开期间导致阻塞等待,这通常是不合需要的,并且如果正在等待的线程依次导致死锁,则可能导致死锁等待线程正在等待的一些动作。
通过让应用程序在这种情况下终止,您作为程序员被迫主动思考会导致对象被销毁的条件,并确保线程正确连接。