C# 中使用 lock 语句的递归/嵌套锁定

发布于 2024-09-18 19:47:07 字数 896 浏览 1 评论 0原文

可能的重复:
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 在幕后施展了某种魔法,从而简单地忽略了源自同一线程的对象上的所有后续锁定?

Possible Duplicate:
Re-entrant locks in C#

I've looked here on StackOverflow and on MSDN, and can't believe that I couldn't find this question lingering out there on the internets.

Let's say I have a class with a private member that I want to access in several public methods. These public methods will be called by different threads, hence the need for synchronization.

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

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

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

Note that MethodA and MethodB can be called by users of this class, but MethodA also calls MethodB, which results in a nested locking condition.

Is this guaranteed to be safe? In other words, does .NET handle this by reference counting the lock, so that as I pop out of these methods, the lock gets decremented? Or is .NET performing some magic behind the scenes, whereby it simply ignores all subsequent locks on the object originating from the same thread?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南风起 2024-09-25 19:47:07

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

Monitor.Enter 的文档中:

同一个线程是合法的
在没有它的情况下多次调用 Enter
阻塞;然而,同等数量的
必须在退出调用之前调用
其他线程正在等待该对象
将解锁。

这究竟是好事还是坏事还有待商榷……

Yes, locks based on Monitor in .NET are recursive, and counted.

From the docs for Monitor.Enter:

It is legal for the same thread to
invoke Enter more than once without it
blocking; however, an equal number of
Exit calls must be invoked before
other threads waiting on the object
will unblock.

Whether this is a good thing or not is up for debate...

过期情话 2024-09-25 19:47:07

是的,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();
        }
    }
}

Yes, Monitor support recursion, but you should be aware because this behavior differs from one synchronization primitive to another.

For example, ReaderWriterLockSlim by default doesn't support recursion and this code snippet throws 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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文