57

可能重复:
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

4 回答 4

87

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

于 2012-10-22T18:18:35.493 回答
22

因为你这里只有一个线程。

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 调用。

于 2012-10-22T18:18:26.100 回答
10

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

于 2012-10-22T18:37:50.277 回答
5

lock声明比这更聪明,它旨在防止这种情况发生。一旦线程进入锁,它就被线程“拥有”,所以只要它到达另一个lock锁在同一个对象上的语句,它就会意识到它已经可以访问那个锁。

于 2012-10-22T18:19:24.640 回答