std :: thread.join()死锁

时间:2013-06-19 13:01:55

标签: c++ multithreading

我不明白为什么这个简单的片段有死锁:

#include <atomic>
#include <thread>
#include <memory>

using namespace std;
class Test {
public:

    Test() : mExit( false )
    {
        mThread = thread( bind( &Test::func, this ) );
    }

    ~Test()
    {
        if ( mThread.joinable() )
        {
            mExit = true;
            mThread.join();
        }
    }

private:
    void func() 
    {
        while ( !mExit )
        {
            // do something
        }
    }

private:
    atomic< bool > mExit;
    thread mThread;
};

typedef unique_ptr< Test > TestPtr;
TestPtr gTest;

int main()
{
    gTest = TestPtr( new Test );
    return 0;
}

修改 我输错了contstructor set mExit = true

编辑2 我正在使用msvc2012和v110_xp工具集。

编辑3 如果我明确地在main

中调用gTest.release(),问题就会消失

3 个答案:

答案 0 :(得分:7)

我刚刚遇到这个问题,所以我发布了其他人的真实答案。

至少在visual studio中,有一个“退出锁定”,当线程进入退出代码时(即在主线程的main()之后,以及f()之后{ {1}})。

由于您的Test类仅在std::thread(f)完成后被破坏,因此“退出锁定”被锁定。只有这样你才能设置main(),并允许其他线程完成。这个其他线程然后等待获取主线程已经采用的“退出锁定”,而主线程在mExit = true;中等待导致死锁。

所以是的,你需要在主线程完成之前加入所有线程。

答案 1 :(得分:3)

对我来说,代码看起来没问题,如果它与本地dut坏了全局我怀疑类与deinit序列相关。连接在退出时发生,并且实现可能已经消除了一些结构。不应该是这种情况,但可能。

在任何情况下,我总是避免在main之前启动线程,并留下main的任何到达端。我认为那只是在惹麻烦。如果你可以重新安排它以在较小的点上强制加入,整个问题可能会消失。

你也应该使用atomic_flag而不是原子。

答案 2 :(得分:0)

更改代码

gTest = TestPtr(新测试);

auto gTest = std :: make_unique();

消除问题。

上面提到全局对象的问题。