使用lock语句在C#中进行递归/嵌套锁定

时间:2010-09-10 18:56:49

标签: c# .net synchronization locking

  

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

我在StackOverflow和MSDN上看到了这个,并且无法相信我无法在互联网上找到这个问题。

假设我有一个私有成员的课程,我想在几个公共方法中访问。这些公共方法将由​​不同的线程调用,因此需要同步。

public class MyClass
{
    private Object SomeSharedData = new Object();

    public void MethodA()
    {
        lock( SomeSharedData) {
            // do something
            MethodB();
        }
    }

    public void MethodB()
    {
        lock( SomeSharedData) {
            // do something
        }
    }
}

请注意,MethodA和MethodB可以由此类的用户调用,但MethodA也调用MethodB,这会导致嵌套锁定条件。

这是否保证安全?换句话说,.NET是通过引用计数锁来处理这个,所以当我弹出这些方法时,锁会减少吗?或者.NET在幕后执行一些魔术,它只是忽略源自同一线程的对象上的所有后续锁定?

2 个答案:

答案 0 :(得分:18)

是的,基于.NET中Monitor的锁是递归的,并且是计数的。

来自Monitor.Enter的文档:

  

同一个线程是合法的   如果没有它,则调用多次   阻塞;但是,数量相等   必须先调用退出调用   等待对象的其他线程   将取消阻止。

这是否是一件好事还有争议......

答案 1 :(得分:4)

是的,Monitor支持递归,但您应该知道,因为这种行为因同一个原语而异。

例如,ReaderWriterLockSlim默认情况下不支持递归,此代码段会抛出异常:

public class MyClass
{
    ReaderWriterLockSlim rw = new ReaderWriterLockSlim();
    //You should explicitly stated that you want to use recursion
    ReaderWriterLockSlim rwWithRecursion = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);

    public void MethodA()
    {
        try {
           rw.EnterReadLock();
           // do something
           MethodB();
        }
        finally {
          rw.ExitReadLock();
        }
    }

    public void MethodB()
    {
        try {
           rw.EnterReadLock(); //throws LockRecursionException
        }
        finally {
          rw.ExitReadLock();
        }
    }
}