C#中的重入锁

下面的代码会导致在.NET上使用C#发生死锁吗?

class MyClass { private object lockObj = new object(); public void Foo() { lock(lockObj) { Bar(); } } public void Bar() { lock(lockObj) { // Do something } } } 

不,只要你locking在同一个对象上。 recursion代码已经有了锁 ,所以可以不受阻碍地继续下去。

lock(object) {...}是使用Monitor类的简写。 正如Marc所指出的那样 , Monitor允许重新进入 ,所以重复尝试locking当前线程已经locking的对象将会工作得很好。

如果你开始locking不同的对象,那么你必须小心。 特别要注意:

  • 始终以相同的顺序获取给定数量的对象的locking。
  • 总是以相反的顺序释放锁,以获取它们。

如果你违反这些规则中的任何一个,你几乎可以保证在某些时候遇到死锁问题。

这是一个很好的网页,描述了.NET中的线程同步: http : //dotnetdebug.ne​​t/2005/07/20/monitor-class-avoiding-deadlocks/

另外,尽可能less的locking对象。 考虑在可能的情况下应用粗粒锁 。 这个想法是,如果你可以写你的代码,使得有一个对象图,并且你可以获得该对象图的根的锁,那就这样做。 这意味着你在这个根对象上有一个锁,因此不必太担心你获取/释放锁的顺序。

(还有一点需要注意,你的例子在技术上并不是recursion的,因为它是recursion的, Bar()将不得不自己调用,通常作为迭代的一部分。

那么, Monitor允许重新进入,所以你不能死锁自己…所以不:不应该这样做

如果一个线程已经持有一个锁,那么它不会阻塞自己。 .Net框架确保了这一点。 你只需要确保两个线程不会试图通过任何代码path获得相同的两个锁。

同一个线程可以多次获得相同的锁,但是您必须确保释放锁的次数与您获得的次数相同。 当然,只要你使用“locking”关键字来实现这一点,它会自动发生。

不,这个代码不会有死锁。 如果你真的想创造死锁最简单的一个需要至less2资源。 考虑狗和骨头的情况。 一只狗可以完全控制一只骨头,所以其他的狗只能等待。 2,2只2只骨头的狗,当他们分别锁骨头,寻找别人的骨头时,最起码造成僵局。

如此这般的狗和米骨,造成更复杂的僵局。