如何创建一个只在调用线程持有锁时运行的方法?

时间:2014-05-08 17:26:59

标签: 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()现在可以被不具备锁定的线程调用。

1 个答案:

答案 0 :(得分:5)

您应该能够使用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之前,AFAIK处理此问题的唯一方法是在同步对象旁边使用线程静态布尔值,在退出之后输入true之后设置为false。同样的布尔值 - 调用它callerHasLock,以符合上面的代码 - 然后可以在锁定上下文中进行测试,结果与Monitor.IsEntered相同。