std :: thread join中的竞争条件

时间:2014-03-11 23:16:02

标签: multithreading visual-studio c++11

在msvc上,如果你试图加入一个不可连接的线程,它将调用abort。所以你必须在调用join之前检查该线程是否可以连接,但是这里的self是一个竞争条件。

void BaseThread::join()
{
    auto thread = m_pPrivates->m_pThread;

    if (!thread)
        return;

    if (thread->get_id() != std::thread::id() && thread->joinable())
        thread->join();
}

如果线程不可连接或更好的方法,是否可以停止调用abort的运行时间?

编辑:

所以这是在visual studio运行时处理线程关闭的函数。

int _Thrd_join(_Thrd_t thr, int *code)
{   /* return exit code when thread terminates */
    unsigned long res;

    if (WaitForSingleObject(thr._Hnd, INFINITE) == WAIT_FAILED || GetExitCodeThread(thr._Hnd, &res) == 0)
        return (_Thrd_error);
    if (code)
        *code = (int)res;
    return (CloseHandle(thr._Hnd) == 0 ? _Thrd_error : _Thrd_success);
}

最后一行(CloseHandle)抛出此异常:

Unhandled exception at 0x7750BCEC (ntdll.dll) in desura.exe: 0xC0000008: An invalid handle was specified. Which then crashes the app

2 个答案:

答案 0 :(得分:5)

它本身并不是一种竞争条件。线程保持可连接状态,直到它被连接,分离或移动为止。这些是你的程序可以控制的所有东西,如果另一个线程正在与你尝试加入的线程异步地执行其中一项,你显然必须同步。但通常情况并非如此,而且您是该主题的所有者/经理。

请注意,仅仅因为线程完成执行,这不会使其无法加入。实际上,即使您可以保证线程已经完成执行,您仍然必须加入它(或分离它等)以防止被调用terminate()

答案 1 :(得分:0)

请参阅上面的评论。请注意,std::thread具有与pthread库非常相似的界面/行为,因此即使pthread,我对std::thread的评论也有效。

您应该在线程上使用的两个操作是“开始”和“加入”。如果您正在使用其他东西或者您正在考虑使用其他东西,那么您的设计就不行了,是时候发布一个关于您的实际线程问题的问题,而不是转向一个糟糕的设计并要求其他人“推动它更难”。 :-) :-): - )

许多线程API /库除了“开始”和“加入”之外还包含几个附加功能,但这些通常只是为了鼓励糟糕的线程设计。在我看来,std::thread::joinable()和线程对象的移动也是没有的东西......