使用lock语句在C#中进行递归/嵌套锁定
可能重复:
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在幕后执行一些魔术,它只是忽略了源自同一线程的对象上的所有后续锁定?
是的,基于.NET in .NET的锁是递归的,并且是计数的。
从Monitor.Enter
的文档:
如果没有阻塞,同一个线程不止一次调用Enter是合法的; 但是,在等待对象的其他线程将解除阻塞之前,必须调用相同数量的Exit调用。
这是否是一件好事还有争议……
是的, Monitor支持递归,但您应该知道,因为这种行为从一个同步原语到另一个同步原语不同。
例如,默认情况下, ReaderWriterLockSlim不支持递归,并且此代码段会引发exception:
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(); } } }