c# - 如何创建一个仅在调用线程持有锁时才运行的方法?

标签 c# multithreading locking c#-3.0

在下面的不安全类中,可以采取什么措施来防止某人在没有先获取锁的情况下执行不安全方法?

class Unsafe
{
    private static readonly object lockObj;

    void MethodA()
    {
        lock (lockObj)
        {
            // do some things
            DoUnsafeThing();
        }
    }

    void MethodB()
    {
        lock (lockObj)
        {
            // do some things
            DoUnsafeThing();
        }
    }

    void DoUnsafeThing()
    {
        if (callerHasLock)
            // Do the unsafe thing
        else
            return; // or throw some exception
    }
}

可以选择在 DoUnsafeThing() 内再次获取锁:

void DoUnsafeThing()
{
    lock (lockObj)
    {
        // Do the unsafe thing
    }
}

但是 DoUnsafeThing() 现在可以由尚未拥有锁的线程调用。

最佳答案

您应该能够使用Monitor.IsEntered()验证线程本身是否已经获得锁:

void DoUnsafeThing()
{
    if (Monitor.IsEntered(lockObj))
        // Do the unsafe thing
    else
        return; // or throw some exception
}

您可以使用Monitor使用锁的类。在 C# 中,lock(...)语句只是 Monitor.Enter(o); try {...} finally {Monitor.Exit(o);} 的语法糖。 。其中还有其他选项可用于微调。请记住,多线程很困难。了解您的工具集。

编辑:(响应框架版本问题更新)

在 .NET 4.5 之前,据我所知,处理此问题的唯一方法是在同步对象旁边使用线程静态 bool 值,设置为 true进入后不久 false就在退出之前。同样的 bool 值——称之为 callerHasLock ,以符合上面的代码 - 然后可以在锁定上下文中进行测试,结果与 Monitor.IsEntered 相同.

关于c# - 如何创建一个仅在调用线程持有锁时才运行的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23548619/

相关文章:

c# - 没有catch block 的finally block 是java反模式吗?

javascript - 在asp.net中使用DropDownList显示和隐藏Div

java - 另一个 ConcurrentModificationException 问题

android - Handler.sendMessageDelayed(msg, delay) 无法正常工作

c++ - c/c++ Linux 允许的最大互斥量

asp.net-mvc-3 - C# lock 关键字,我想我用错了

c# - WCF 如何处理实例化和并发性?

c# - 如何在 net core 代码脚手架中添加新目标

python 2.7 : Thread local storage's instantiation when first accessed?

git - 为什么基于 merge 的 SCM 优于基于锁的系统?