10

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

#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 我正在使用带有 v110_xp 工具集的 msvc2012。

编辑 3 如果我在 main 中明确调用 gTest.release(),问题就会消失

4

3 回答 3

8

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

至少在visual studio中,有一个“退出锁”,当线程进入退出代码时被锁定(即main()在主线程之后,在之后f()std::thread(f)

由于您的 Test 类仅在main()完成后被破坏,因此“退出锁”被锁定。只有这样,您才可以设置mExit = true;并允许其他线程完成。然后这个其他线程等待获得已经被主线程占用的“退出锁”,而主线程等待mThread.join();导致死锁。

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

于 2015-05-26T13:33:19.910 回答
3

对我来说,代码看起来还不错,如果它可以与本地 dut 和 global 我怀疑与 deinit 序列相关的类。连接发生在出口的深处,实施可能已经消除了一些结构。它不应该是这种情况,但可能。

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

此外,您可能应该在 atomic 上使用 atomic_flag。

于 2013-06-19T13:39:11.207 回答
0

更改代码

gTest = TestPtr(新测试);

自动 gTest = std::make_unique();

消除问题。

上述问题与全局对象有关。

于 2017-06-04T00:12:34.683 回答