这是一些伪代码来解释我的情况。我正在使用QThreads,但解决方案可能与Qt无关。
class ResourceOwner
{
// Spawns worker on new QThread, initiates Worker::doWork()
void spawnWorker(resource); {...}
void deleteResourceSafely(); // How do you implement this function?
private:
Resource *resource;
Worker *worker;
}
class Worker
{
void doWork() { while(true) resource->doSomething(); }
void cleanupSelf() {...};
private:
Resource *resource;
}
void main()
{
ResourceOwner owner();
owner.spawnWorker();
...
// Some time later after enough work has been done
owner.deleteResourceSafely();
}
当需要删除resource
时,我们需要关闭工作人员。但是,Worker
可能正在访问resource
。
如果刚删除resource
,则Worker
将崩溃,因为它会访问无效内存。我可以阻止Worker
所属的主题,但Worker
将无法正常清理自己。
所以我如何中断Worker
的{{1}}功能,告诉它自我清理并停止访问doWork()
?
答案 0 :(得分:1)
一种常见且简单的方法是让线程定期检查一个标志。如果已设置,则线程自行终止。
答案 1 :(得分:0)
鉴于您已经使用Qt,我建议尝试删除资源的线程应该向工作线程发送信号,然后等待工作线程因信号而终止。显然你需要实现一个合适的信号处理程序。
答案 2 :(得分:0)
如joachim所述,有一个标志,您定期检查工作线程。向Worker添加一个函数,称为requestStop,它将volatile bool或QAtomicInt设置为false,表示该线程应该退出run()。使用volatile bool确保编译器不会优化对它的访问。你的工作项应经常检查这个标志,如果它变为false,它应该确保它从run()asap返回。没有提到的是在设置标志后,在线程上调用wait()以使其退出。一旦调用wait()返回,线程就停止了,因此删除资源是安全的。
部分替代方法是使用引用计数资源来避免调用wait()。如果您的资源在工作线程中有一个指向它的共享指针,那么如果主线程删除对它的引用并标记线程(或工作项)以完成,则工作线程/项可以在完成时删除对它的引用并销毁如果它是唯一的剩余所有者。即这个aproach将适用于线程池,你不会等待线程完成,因为工作项排队了。