【发布时间】:2018-10-30 06:32:56
【问题描述】:
我有一个主线程,我在其中创建了一些自包含的类实例。
实例本身包含大量数据,需要经常删除和重新创建。实际删除它们需要一段时间(包含大量数据的 10 万个实例 == 删除时间长),所以我的想法是将它们的删除卸载到单独的线程,因此允许 UI 在它们时保持响应被删除并清理内存。
这是一些伪代码,显示了我要删除的类:
class myObj
{
std::vector<int> bigData; //eventually filled with lots of data
};
这里有一些伪代码来展示默认的阻塞删除方法是如何工作的:
void deleteStuff (std::vector<myObj*> *objects) //this works fine
{
for (auto obj : *objects)
{
delete obj;
}
objects->clear();
}
但是当我以这种方式删除内容时,我的程序会崩溃。为什么?
void deleteStuffThreaded(std::vector<myObj*> *objects)
{
for (auto obj : *objects)
{
delete obj;
}
objects->clear();
}
void deleteStuff(std::vector<myObj*> *objects) //this crashes
{
std::thread deleteThread(&deleteStuffThreaded, objects);
}
值得注意的是,一旦 deleteStuff 返回,“objects”向量就不会再被触及,因此在线程中清除“objects”和在其他地方访问它之间的代码中其他地方不会发生竞争条件。有时,当我单步执行代码时,“deleteStuffThreaded”函数会在到达“clear”行之前崩溃。
Google 告诉我理论上可以在与创建对象不同的线程中删除对象,而且我知道崩溃不是由在“deleteStuff”返回后尝试访问已删除对象之一的属性引起的,因为单线程版本工作正常(我检查了我的代码,这些实例再也没有被触及过)。
【问题讨论】:
-
是否有其他线程使用该
vector或该vector的副本?如果是,崩溃几乎是意料之中的。 -
在删除
myObj之前,您似乎没有使用任何互斥锁来确保没有其他人在使用它。单线程版本可以正常工作,因为代码是按顺序运行的,而在这里您可以调用deleteStuff然后继续访问myObj -
@user4581301 不,我编辑了我的问题以添加一个关于那个的注释......那个向量再也没有被触及(为了争论,考虑到它的指针也没有被删除)。
-
@Tas 我不明白为什么我需要一个互斥锁......在“deleteStuff”返回后,那些 myObj 实例再也不会被触及。如果是,单线程的“deleteStuff”也会产生错误。
-
这个傻逼有minimal reproducible example 的机会吗?我知道多线程 MCVE 让人头疼,但我们不能对所描述的代码做出任何好的陈述。很明显,某处遗漏了一些东西,或者它不会爆炸,如果你知道它是什么并且可以将它添加到描述中,你可能不会问这个问题。
标签: c++ multithreading class