有条件地使用线程中的锁?

时间:2018-03-27 16:04:05

标签: c# .net multithreading

我有一个多线程使用的方法。在该方法中,有一些关键代码,我必须使用锁,只允许一个线程访问它。所以,代码看起来像:

private void RunCode()
{
    ......  // some other codes
    lock (myLock)
    {
        ......  // critical code01
    }

    ......  // some other codes

    lock (myLock)
    {
        ......  // critical code02
    }

    ....... // some other codes
}

此代码由多线程使用。现在,由于一些工作流程的更改,我们希望保持代码按原样运行,但在某些特殊情况下,我们希望在没有锁定的情况下立即运行关键代码。即使计算结果不是100%正确,我们也可以,因为我们没有锁定它。因此,代码应如下所示:

private void RunCode(bool isSpecial)
{
    ......  // some other codes
    lock (myLock)   // if isSpecial == true, do not lock it, otherwise, lock it
    {
        ......  // critical code01
    }

    ......  // some other codes

    lock (myLock)   // if isSpecial == true, do not lock it, otherwise, lock it
    {
        ......  // critical code02
    }

    ....... // some other codes
}

基于研究,似乎我们必须做类似

的事情
if (isSpecial)
{
    ......  // critical code01

}
else
{
    lock (myLock)
    {
        ......  // critical code01
    }
}

它会起作用,但问题是我们必须重复两次关键code01(和code02)。这些代码非常复杂,与RunCode()方法中的其他代码密切相关。

我的问题是:有更好的方法吗?有什么建议?我们正在使用c#.net,但欢迎任何建议。

由于

3 个答案:

答案 0 :(得分:2)

尝试直接使用Monitor课程。它有一个方法TryEnter
像这样重写你的代码:

try
{
    if (isSpecialCase || Monitor.TryEnter(myLock, TimeSpan.MaxValue))
    {
        // critical code01
    }
}
finally
{
    if (!isSpecialCase)
    {
        // lock was taken
        Monitor.Exit(myLock);
    }
}

答案 1 :(得分:1)

至少可以说,你想做什么听起来很奇怪。但如果我不能没有它,我会尝试动态定义一个lambda表达式并在这两个位置调用它。

的内容
int aNumber = 5;

Action criticalCode01 = () => {Console.WriteLine("Foo! (repeat "+aNumber+" times)");};

if (isSpecial)
{
    criticalCode01();
}
else
{
    lock (myLock)
    {
        criticalCode01();
    }
}

答案 2 :(得分:0)

这就是你要找的东西:

try
{
    if (!isSpecialCase) Monitor.Enter(myLock);

    // critical code01
}
finally
{
    if (!isSpecialCase) Monitor.Exit(myLock);
}