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

Eri*_*ric 53 .net c# deadlock locking

可能重复:
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();
}
Run Code Online (Sandbox Code Playgroud)

我得到输出:

Foo
Bar
Run Code Online (Sandbox Code Playgroud)

我预计这会陷入僵局,因为Foo获得了一个锁,然后等待Bar获得锁.但这不会发生.

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

thu*_*eys 80

对于同一个线程,锁总是可重入的,因此线程可以根据需要随时锁定对象.

  • +1关键字是"可重入"; 不可重入的锁(例如文件锁)会死锁. (6认同)
  • +1折返很酷 (3认同)
  • 谢谢,折返是我缺乏的术语,以及为什么我无法在Google上快速找到答案. (3认同)
  • 如果一个线程可以多次获取锁,并且必须多次释放,则称为*递归*.也许不是在C#中,但只是你知道. (2认同)

Ser*_*kiy 21

因为这里只有一个线程.

lock 是的捷径

bool lockWasTaken = false;
var temp = obj;
try { 
       Monitor.Enter(temp, ref lockWasTaken); 
       // your thread safe code
}
finally { if (lockWasTaken) Monitor.Exit(temp); }
Run Code Online (Sandbox Code Playgroud)

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

  • +1 表示在单独的线程访问权限之前有关相同数量的退出调用的通知 (2认同)

小智 9

One word: Reentrant lock. If a thread has already acquired a lock, then it does not wait if it wants to acquire the lock again. This is very much needed otherwise it could have turned simple recursive functions into a nightmare.!

  • 两个字:两个字. (30认同)

Ser*_*rvy 5

lock声明是聪明得多,它是为了防止仅此.一旦线程进入其中,锁就被"拥有",所以当它到达另一个lock锁定同一对象的语句时,它将意识到它已经可以访问该锁.