以下代码是否会在.NET上使用C#导致死锁?
class MyClass
{
private object lockObj = new object();
public void Foo()
{
lock(lockObj)
{
Bar();
}
}
public void Bar()
{
lock(lockObj)
{
// Do something
}
}
}
答案 0 :(得分:139)
不,只要您锁定同一个对象即可。 的递归代码已经具有锁,因此可以继续畅通无阻。
lock(object) {...}
是使用Monitor类的简写。由于Marc points out,Monitor
允许 re-entrancy ,因此重复尝试锁定当前线程已锁定的对象 会工作得很好。
如果你开始锁定不同的对象,那就必须要小心了。特别注意:
如果你破坏了这些规则中的任何一个,你几乎可以保证在某些时候出现死锁问题。
这是一个很好的网页,用于描述.NET中的线程同步:http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
此外,尽可能锁定少量对象。考虑尽可能应用coarse-grained locks。我们的想法是,如果您可以编写代码,使得存在对象图,并且您可以获取该对象图的根上的锁,那么就这样做。这意味着您对该根对象有一个锁定,因此不必担心获取/释放锁定的顺序。
(另外请注意,您的示例在技术上不是递归的。要使其递归,Bar()
必须调用自身,通常作为迭代的一部分。)
答案 1 :(得分:19)
好吧,Monitor
允许重入,所以你不能让自己陷入僵局......所以不:它不应该做
答案 2 :(得分:6)
如果一个线程已经持有一个锁,那么它就不会阻塞它自己。 .Net框架确保了这一点。您只需要确保两个线程不会尝试通过任何代码路径无序地获取相同的两个锁。
同一个线程可以多次获取同一个锁,但你必须确保释放锁的次数与你获取的次数相同。当然,只要您使用“lock”关键字来完成此操作,它就会自动发生。
答案 3 :(得分:5)
不,这段代码不会有死锁。 如果你真的想创建最简单的死锁,那么至少需要2个资源。 考虑狗和骨头场景。 一条狗可以完全控制一根骨头,所以任何其他狗都要等。 2.当他们分别锁住骨头并寻找其他骨头时,最少需要2只带有2块骨头的狗来制造死锁。
..等等n狗和骨头,造成更复杂的死锁。