为什么Lock'ing在同一个对象上导致死锁?

时间:2012-10-22 18:16:45

标签: c# .net locking deadlock

  

可能重复:
  Re-entrant locks in C#

如果我写这样的代码:

class Program {
    static void Main(string[] args) {
        Foo();
        Console.ReadLine();
    }

    static void Foo() {
        lock(_lock) {
            Console.WriteLine("Foo");
            Bar();
        }
    }

    static void Bar() {
        lock(_lock) {
            Console.WriteLine("Bar");
        }
    }

    private static readonly object _lock = new object();
}

我得到了输出:

Foo
Bar

我预计这会死锁,因为Foo获得了一个锁,然后等待Bar获得锁。但这不会发生。

锁定机制是否只允许这样做,因为代码是在同一个线程上执行的?

4 个答案:

答案 0 :(得分:75)

对于同一个线程,锁始终是reentrant,因此线程可以根据需要随时锁定对象。

答案 1 :(得分:21)

因为这里只有一个帖子。

lock

的捷径
bool lockWasTaken = false;
var temp = obj;
try { 
       Monitor.Enter(temp, ref lockWasTaken); 
       // your thread safe code
}
finally { if (lockWasTaken) Monitor.Exit(temp); }

Monitor.Enter获取作为参数传递的对象的Monitor。如果另一个线程在对象上执行了Enter但尚未执行相应的Exit,则当前线程将阻塞,直到另一个线程释放该对象。 同一个线程在没有阻止的情况下多次调用Enter是合法的;但是,在等待对象的其他线程将解除阻塞之前,必须调用相同数量的Exit调用。

答案 2 :(得分:8)

一个字:可重入锁定。如果一个线程已经获得了一个锁,那么如果它想要再次获取锁,它就不会等待。这是非常需要的,否则它可能会将简单的递归函数变成一场噩梦。!

答案 3 :(得分:5)

lock语句比这更聪明,它旨在防止这种情况发生。一旦线程进入其中,锁就被“拥有”,所以当它到达锁定同一对象的另一个lock语句时,它将意识到它已经可以访问该锁。

相关问题