如果我理解正确,那么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_);
}
答案 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
,并且调用者忽略返回的错误值。