如何使一个方法只在调用线程持有锁时运行

本文关键字:运行 线程 调用 何使一 方法 | 更新日期: 2023-09-27 18:02:20

在下面的不安全类中,可以做些什么来防止某人在没有首先获得锁的情况下执行不安全的方法?

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);}的语法糖。还有其他选项可以进行微调。记住,多线程很难。了解你的工具集。

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

在。net 4.5之前,我想处理这个问题的唯一方法是在同步对象旁边使用线程静态布尔值,在进入后设置为true,在退出前设置为false。然后可以在锁上下文中测试相同的布尔值(称为callerHasLock,以符合上面的代码),得到与Monitor.IsEntered相同的结果。