Closed. This question is
off-topic。它当前不接受答案。
想改善这个问题吗?
Update the question,所以它是
on-topic,用于堆栈溢出。
4年前关闭。
我无法发布源代码,但是可以在概念上解释它的一部分,希望可以帮助我理解我的解决方案为什么起作用。
我有一个具有3个线程的应用程序:A,B和C(主线程)。
线程B具有Foo对象的列表。
每个Foo对象正好包含1个Mutex对象,这是递归互斥对象的包装,以及一堆用于使用Mutex以同步方式设置和获取各种属性的方法,其中2个方法用于设置和获取markedForDelete属性。
线程B所做的全部工作是使用迭代器遍历该列表,并删除标记为删除的Foo对象,否则执行其他指令。它是唯一使用类似于以下代码的销毁Foo对象的线程:
while (running)
{
fooListLock->Lock();
for (vector<Foo*>::iterator it = fooList.begin(); it)
{
if (it->isMarkedForDelete())
{
it = fooList.erase(it);
}
else
{
it->execute();
}
}
fooListLock->Unlock();
sleep (sleepVariable);
}
线程A和C将创建Foo对象并将其添加到列表中,它们也可以将它们标记为要删除,并且使用其他互斥对象以同步方式完成操作。
线程C有时会关闭,并且总是在之后重新启动,但是以受控的方式进行,并且永远不会在内存分配/释放期间进行,并且始终会释放锁定的互斥体。
问题是,当Foo的Mutex在堆内存中分配(通过
new
运算符)时,应用程序将进入死锁状态,其中线程C要访问线程A锁定的资源,而前者想要访问线程B锁定的资源。线程B被Foo's Mutex锁定,该互斥锁已锁定,但没有所有者。使用GDB,我发现Mutex的pthread_mutex_t所有者值为0或负数,与任何线程的ID不对应。死锁的阻塞端发生在线程B:
if (it->isMarkedForDelete())
的这段代码中。
我非常直观的解决方案是在堆栈上分配Foo's Mutex,它无需任何其他修改即可工作!应用程序永远不会以这种方式达到死锁状态。
使用设置了O2标志的g ++ 4.8完成编译。
我知道这没什么大不了的,但是有人可以帮助我了解我的解决方案为何起作用吗?