我目前正在编写一个多线程程序,根据某些情况,有时可能会创建一个线程。如果创建了这个线程,它需要独立于所有其他线程运行,我不能阻止任何其他线程等待它加入。生成的线程运行的时间长度各不相同;有时它可能需要几个小时。
我尝试生成线程并在类的析构函数中放入一个正常工作的连接,但是如果生成的线程中的代码在析构函数被调用之前很长时间(这将是大约99%的时间)我希望线程能够自行解放所有资源等。
我考虑使用detach,但是你不能重新加入一个分离的线程,并且在这个线程完成之前调用析构函数然后生成的线程将无法完成并且可能产生灾难性的后果。
是否有任何可能的解决方案可以确保线程在类被破坏之前完成,并且一旦线程完成其工作就允许它加入?
我正在使用boost / c ++ 11进行线程化。任何帮助都将非常感激。
谢谢
答案 0 :(得分: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();
}
};
答案 1 :(得分:1)
您可以在"独立"中定义暂停/步骤线程算法,并在每一步中查看一个全局变量,帮助您决定取消计算并自动销毁,或继续计算您的线程。
如果全局变量不够,即如果需要更精确的粒度,则应为线程函数定义一个仿函数对象,该仿函数具有方法kill()。在将它们作为线程启动后,您将保留对仿函数的引用。当你调用MyThreadFunctor :: kill()时,它会设置一个布尔字段,并在函数线程函数本身的计算的每个步骤中检查该字段。