我无法发布源代码,但我可以在概念层面上解释它的一部分,并希望我能帮助理解我的解决方案的工作原理。
我有一个有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的互斥锁阻止,该互斥锁被锁定但没有所有者。使用GDB我发现Mutex的pthread_mutex_t所有者值为0或负数,不对应于任何线程的id。死锁的阻塞结束发生在线程B中的这段代码:if (it->isMarkedForDelete())
。
我非常直观的解决方案是在堆栈上分配Foo的Mutex,它无需任何其他修改即可运行!应用程序不会以这种方式达到死锁状态。
使用g ++ 4.8设置O2标志进行编译。
我知道继续下去并不多,但是有人可以帮我理解为什么我的解决方案有效吗?
答案 0 :(得分:1)
我当然相信,它与堆错误无关。最有可能的是,您没有正确初始化互斥锁。你在调用pthread_mutex_initialize吗?