锁定aqcuired并进一步尝试锁定不阻塞:C#锁是否重入?

我已经编写了一个测试,我认为应该是一个有效的死锁案例。 看来,一旦一个类的实例获取了lock ,该实例就不再需要重新获取lock ,即使我明确地尝试调用另一个应该再次lock方法。

这是class级:

 internal class Tester { private readonly object _sync = new object(); public Tester() { } public void TestLock() { lock (_sync) { for (int i = 0; i < 10; i++) { Deadlock(i); } } } private void Deadlock(int i) { lock (_sync) { Trace.WriteLine(i + " no deadlock!"); } } } 

输出:

0没有死锁!
1没有死锁!
2没有死锁!
3没有死锁!
4没有死锁!
5没有死锁!
6没有死锁!
7没有死锁!
8没有死锁!
9没有死锁!

我原以为这会导致僵局……任何人都能对此有所了解吗?

.NET中的锁是可重入的。 仅阻止来自其他线程的采集。 当同一个线程多次锁定同一个对象时,它只是增加一个计数器,并在释放时减少它。 当计数器达到零时,锁实际上被释放以便从其他线程访问。

Monitor,Mutex和ReaderWriterLock类维护具有线程关联的锁。 ReaderWriterLockSlim类允许您选择,它具有一个采用LockRecursionPolicy值的构造函数。 使用LockRecursionPolicy.NoRecursion是一种优化,如果你的锁定非常精细,那么这是一个相当大的优化。

Semaphore类是一个没有任何线程关联的同步类。 此代码可靠地死锁:

 class Tester { private Semaphore sem = new Semaphore(1, 1); public void TestLock() { sem.WaitOne(); for (int i = 0; i < 10; i++) Deadlock(i); sem.Release(); } private void Deadlock(int i) { if (!sem.WaitOne(100)) Console.WriteLine("deadlock!"); else { sem.Release(); Console.WriteLine("No deadlock!"); } } } 

通常,线程仿射同步类需要两个线程和两个锁来解锁。 标准模式是一个线程获取锁A和B,另一个线程获取B和A.顺序很重要。

.NET编程中存在不太明显的死锁情况,这是由锁无法看到的,因为它们内置于.NET框架代码中。 一个非常经典的是BackgroundWorker。 您可以在Busy属性上旋转的UI线程中编写代码,等待BGW完成。 当BGW具有RunWorkerCompleted事件处理程序时,它总是会死锁。 它在UI线程空闲之前无法运行,在事件处理程序完成运行之前,BGW的Busy属性不会为false。

在您的方案中,您在另一个锁中有一个锁。 一旦代码命中“死锁”中的嵌套锁,“锁定(…)”代码基本上被忽略,因为它已经在“TestLock”中获取了它。

线程的重要来源: http : //www.albahari.com/threading/part2.aspx 。