Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在函数中使用静态互斥时出现无法解释的死锁情况_Multithreading_C++11_Singleton_Mutex - Fatal编程技术网

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
的东西的结尾