4

我目前正在编写一个多线程程序,有时可能会根据某些情况创建一个线程。如果创建了这个线程,它需要独立于所有其他线程运行,我不能阻止任何其他线程等待它加入。生成的线程运行的时间长度各不相同;有时可能需要几个小时。

我已经尝试生成线程并在类的析构函数中加入一个工作正常的连接,但是如果生成的线程中的代码在调用析构函数之前完成很长时间(大约 99% 的时间)我会就像线程杀死自己释放所有资源等。

我研究过为此使用分离,但您不能重新加入分离的线程,并且如果在该线程完成之前调用析构函数,则生成的线程将无法完成并可能产生灾难性的后果。

是否有任何可能的解决方案可以确保线程在类被破坏之前完成,并允许它在线程完成工作后立即加入?

我正在使用 boost/c++11 进行线程化。任何帮助都将不胜感激。

谢谢

4

2 回答 2

4

线程可能会自行分离,释放其资源。如果析构函数看到线程是可加入的,即仍在运行,让它加入。如果线程到达终点,则自分离。可能的竞争条件:is_joinable() 在析构函数中返回 true - 线程自行分离 - 析构函数加入并惨遭失败。所以使用互斥锁来保护线程的死亡:

struct ThreadContainer
{
   std::mutex threadEndMutex;
   std::thread theThread;

   ThreadContainer()
     : theThread([=]()
       {
         /* do stuff */

         // if the mutex is locked, the destructor is just
         // about to join, so we let him.
         if (threadEndMutex.try_lock())
           theThread.detach();
       })
   {}

   ~ThreadContainer()
   {
     // if the mutex is locked, the thread is just about 
     // to detach itself, so no need to join.
     // if we got the mutex but the thread is not joinable, 
     // it has detached itself already.
     if (threadEndMutex.try_lock() && theThread.is_joinable())
       theThread.join();
   }
};

PS:您甚至可能不需要调用 is_joinable,因为如果线程自行分离,它永远不会解锁互斥锁并且 try_lock 失败。

PPS:您可以使用 std::atomic_flag 代替互斥锁:

struct ThreadContainer
{
   std::atmoic_flag threadEnded;
   std::thread theThread;

   ThreadContainer()
     : threadEnded(ATOMIC_FLAG_INIT)
     , theThread([=]()
       {
         /* do stuff */

         if (!threadEnded.test_and_set())
           theThread.detach();
       })
   {}

   ~ThreadContainer()
   {
     if (!threadEnded.test_and_set())
       theThread.join();
   }
};
于 2012-11-27T10:25:57.193 回答
1

您可以在“独立”线程算法中定义暂停/步骤,并在每个步骤中查看一个全局变量,该变量可帮助您决定取消计算和自动销毁,或继续线程中的计算。

如果全局变量不够用,即如果需要更精确的粒度,您应该为您的线程函数定义一个仿函数对象,这个仿函数有一个方法kill()。在将仿函数作为线程启动后,您会保留对仿函数的引用。当您调用 MyThreadFunctor::kill() 时,它会设置一个布尔字段,并且在仿函数线程函数本身的计算的每个步骤中都会检查该字段。

于 2012-11-27T10:12:53.673 回答