Multithreading 在函数中使用静态互斥时出现无法解释的死锁情况
下面的代码是我正在处理的实际代码的极端简化。这只是为了让任何人都能够重现我所面临的问题Multithreading 在函数中使用静态互斥时出现无法解释的死锁情况,multithreading,c++11,singleton,mutex,Multithreading,C++11,Singleton,Mutex,下面的代码是我正在处理的实际代码的极端简化。这只是为了让任何人都能够重现我所面临的问题 #include <mutex> #include <thread> using std::mutex; using std::thread; void Do() { static mutex myMutex; static int dataToProtect; return; } class MyClass { public: ~MyClas
#include <mutex>
#include <thread>
using std::mutex;
using std::thread;
void Do()
{
static mutex myMutex;
static int dataToProtect;
return;
}
class MyClass
{
public:
~MyClass()
{
mythread_.join();
}
void RunMyThread()
{
mythread_ = thread(&Do);
}
static MyClass *Instance()
{
static MyClass single;
return &single;
}
private:
MyClass()
{}
std::thread mythread_;
};
int main()
{
MyClass::Instance()->RunMyThread();
return 0;
}
看起来是线程和单例设计的组合造成了这个问题,因为如果我不使用线程调用Do():
void RunMyThread()
{
// mythread_ = thread(&Do);
Do();
}
程序执行到最后。
或者,如果我通过公开构造函数绕过单例设计,并通过MyClass实例调用RunMyThread():
int main()
{
// MyClass::Instance()->RunMyThread();
MyClass o;
o.RunMyThread();
return 0;
}
程序也会执行到最后
现在,如果我在Linux上用gcc编译顶部的原始代码,就没有问题了。程序执行到最后
我搞不清楚这段代码中的哪些行为依赖于平台。有什么想法吗 这很可能是由于在Windows运行时清理内容的顺序造成的。您可以通过如下方式向类添加显式调用来测试这一点:
ShutDown()
{
mythread_.join();
}
将join调用从析构函数中取出。然后在您的主要功能中:
int main()
{
MyClass::Instance()->RunMyThread();
MyClass::Instance()->ShutDown();
return 0;
}
这很可能是由于在Windows运行时清理内容的顺序造成的。您可以通过如下方式向类添加显式调用来测试这一点:
ShutDown()
{
mythread_.join();
}
将join调用从析构函数中取出。然后在您的主要功能中:
int main()
{
MyClass::Instance()->RunMyThread();
MyClass::Instance()->ShutDown();
return 0;
}
考虑到前面的注释/答案,这个问题的一个简单答案是:允许线程在主函数返回后执行是导致未定义行为的原因。
(如果代码可移植性是一项要求,应该避免。)考虑到前面的注释/答案,这个问题的简单答案是:允许线程在主函数返回后执行是导致未定义行为的原因。
(如果需要代码可移植性,则应避免这种情况。)是有两个线程卡住了,还是只有一个?您是否检查过它们的堆栈跟踪,包括反汇编?你怎么知道它会卡在那里。您的
线程
没有在main
结束之前完成,我相信这会导致您的行为在标准中未得到充分指定…@Yakk线程在main结束之前完成,因为主线程正在MyClass析构函数中等待子线程。我知道执行会卡在子线程中,因为当我将断点放在“static mutex myMutex”上时,主线程已经在MyClass析构函数中的“mythread_uz.join();”处等待子线程。现在,当我试图用调试器在这一点之后跳过时,执行会被卡住。对不起,我没有解释反汇编代码的技能。不是主线程,而是main
函数。main
结束后,功能静态会被破坏。根据我的经验,main
结束后的线程状态和行为在标准中是极不明确的。请注意,看起来像这样的文本意味着我指的是代码中的单词<代码>主< /代码>,代码中的一个词只出现在C++中,用于<代码>主< /C>函数。因此,“主main
的结尾”是指代码中名为main
的东西的结尾是有两条线卡住了,还是只有一条?您是否检查过它们的堆栈跟踪,包括反汇编?你怎么知道它会卡在那里。您的线程
没有在main
结束之前完成,我相信这会导致您的行为在标准中未得到充分指定…@Yakk线程在main结束之前完成,因为主线程正在MyClass析构函数中等待子线程。我知道执行会卡在子线程中,因为当我将断点放在“static mutex myMutex”上时,主线程已经在MyClass析构函数中的“mythread_uz.join();”处等待子线程。现在,当我试图用调试器在这一点之后跳过时,执行会被卡住。对不起,我没有解释反汇编代码的技能。不是主线程,而是main
函数。main
结束后,功能静态会被破坏。根据我的经验,main
结束后的线程状态和行为在标准中是极不明确的。请注意,看起来像这样的文本意味着我指的是代码中的单词<代码>主< /代码>,代码中的一个词只出现在C++中,用于<代码>主< /C>函数。因此,“主main
的结尾”是指代码中名为main
的东西的结尾