Pthreads-锁定,2次解锁

时间:2010-08-12 19:13:16

标签: c++ c locking pthreads mutex

如果我理解正确,那么foo1()无法解锁& private_value_。因此,foo2()的thread_mutex_lock不起作用,因为foo1()从未发布过它。

其他后果是什么?

int main ( ... )

foo1();
foo2();

return 0;
}

foo1()
{
 pthread_mutex_lock(&private_value_);
 do something 
 // no unlock!
}

foo2()
{
 pthread_mutex_lock(&private_value_)
 do something
 pthread_mutex_unlock(&private_value_);
}

8 个答案:

答案 0 :(得分:5)

程序应该的编写方式与当前编写的程序 的行为方式之间似乎存在一些混淆。

此代码导致死锁,这并不表示互斥锁的工作方式有问题。它们正在按照它们的预期工作:如果您尝试重新获取已经锁定的非递归互斥锁,则代码将阻塞,直到互斥锁被解锁。这就是它应该如何运作。

由于此代码是单线程的,foo2中的阻塞将永远不会结束,因此您的程序将会死锁而不会进展。这很可能不是程序应该的工作方式(因为它不是一个非常有用的程序)。错误不在于互斥体的运行方式,而在于程序员如何选择使用它们。程序员 应该在foo1结束时进行解锁通话。

答案 1 :(得分:4)

互斥锁工作正常。它正在做它应该做的事情。在foo1()退出之后线程将阻塞,直到foo2获得互斥锁。

答案 2 :(得分:1)

这就是为什么人们迁移到提供基于范围的解决方案的语言,比如C ++和RAII。互斥锁正在按预期工作,但第一个函数的编写者忘记了一个小调用,现在应用程序停止了。

答案 3 :(得分:1)

如果锁定在互斥锁上并且没有任何东西释放锁定,那就是一个错误。

然而,这并不一定意味着foo1()必须释放锁定,但必须要有。

有些模式会让一个函数获取一个锁,而另一个函数会释放它。但是您需要特别注意这些更复杂的互斥锁处理模式是否正确编码。您可能正在查看此示例(问题中的简化代码段不包括其他复杂性)。

正如Neil Butterworth在评论中提到的那样,在C ++中有许多情况,其中互斥体将由RAII类管理,因此当“锁定管理器”对象被破坏时(通常通过外出),锁将自​​动释放范围)。在这种情况下,锁定被释放可能并不明显,因为这是因为变量的副作用仅仅超出了范围。

答案 4 :(得分:1)

不,它不一定阻止。全部取决于您的private_value_变量。 pthread_mutex_t可以根据初始化变量时设置的属性显示不同的行为。见http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_lock.html

答案 5 :(得分:1)

回答这个问题:

除了死锁之外没有其他后果(因为你的例子是单线程并同步调用)..

答案 6 :(得分:0)

如果只调用foo2,一切都会正常运行。如果foo1被调用,那么,如果调用foo2或任何其他需要互斥锁的函数,它将永远锁定。

答案 7 :(得分:0)

此代码的行为取决于互斥锁的类型:

  • 默认值:未定义的行为(锁定已锁定的互斥锁)。
  • 正常:死锁(锁定已锁定的互斥锁)。
  • 递归:正常工作,但是互斥锁被锁定(因为它被锁定了两次但只解锁了一次)。
  • 错误检查:完全正常工作,并在结束时解锁互斥锁(第二次锁定调用失败并显示EDEADLK,并且调用者忽略返回的错误值。