可连接的std :: thread不能自动加入的原因是什么?

时间:2014-01-24 13:50:11

标签: c++ multithreading c++11 thread-safety language-lawyer

有时,如果可连接的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本身。

1 个答案:

答案 0 :(得分:15)

原因很简单,你不得不考虑它。如果由于异常转义范围而导致std::thread对象被销毁,则连接可能会在堆栈展开期间导致阻塞等待,这通常是不合需要的,并且如果正在等待的线程依次导致死锁,则可能导致死锁等待线程正在等待的一些动作。

通过让应用程序在这种情况下终止,您作为程序员被迫主动思考会导致对象被销毁的条件,并确保线程正确连接。