【问题标题】:Performance degradation when using lock inside try在 try 中使用 lock 时性能下降
【发布时间】:2016-06-30 07:05:00
【问题描述】:

我有一个用于单元测试的MockHttpListener 回调。我给它加了一个锁,如下所示:

public void HandleRequest(HttpListenerContext context)
{
    try
    {
        lock (m_guard)
        {
            do something short;
        }

        do the actual handling (longer)
    }
    catch (HttpListenerException e)
    {
        ...
    }
    catch (Exception e)
    {
        ...
    }
    ...
}

我遇到了一个测试失败的问题,因为我们有“花费太长时间”的标准(我在添加锁之前的测试中没有遇到这个问题。)

我尝试了很多方法来确定问题,唯一解决问题的方法是将锁放在 try 块之外:

public void HandleRequest(HttpListenerContext context)
{
    lock (m_guard)
    {
        do something short;
    }
    try
    {
        do the actual handling (longer)
    }
    catch (HttpListenerException e)
    {
        ...
    }
    catch (Exception e)
    {
        ...
    }
    ...
}

在相对于 try 块的锁定位置影响测试完成的持续时间方面,行为变化是一致的。

有人知道原因吗?

【问题讨论】:

  • 考虑阅读此stackoverflow.com/questions/5997360/…。它会让你知道它为什么会发生。
  • @hazevich 这并没有告诉你为什么它更慢,但它确实告诉你你不应该允许未处理的异常从lock中逃脱块。您需要在lock 块内使用try/finally 来清理内容。但这对这里的 OP 没有帮助,我认为。
  • 我阅读了链接中的线程,但它讨论了在 try 块中使用锁的正确性。我只对性能影响感兴趣。考虑到所有考虑的锁定块可以认为仅由:m_some_member++组成;没有别的,所以它本身就很安全。
  • 如果您只是在读取然后有条件地递增,您可以尝试使用 ReaderWriterLockSlim (msdn.microsoft.com/en-us/library/…) 而不是锁。在某些情况下,联锁 (msdn.microsoft.com/en-us/library/…) 也可能是一个不错的选择。
  • 太长还是挂起?如果是后者,则表明锁定逻辑本身存在问题(对代码的任何更改都可能改变时序)。实际上,这也可能是前者的原因,尽管可能性较小。在其他个地方会发生什么情况?

标签: c#


【解决方案1】:

这听起来可能是一个死锁 - “做一些简短的事情”代码是否会调用任何本身需要锁定的代码?

以下代码按预期工作 - 并不是说​​这是一个好主意,但它会毫无问题地终止。

class Program
{
    static void Main(string[] args)
    {
        Locks.DoStuff(Enumerable.Range(0, 10000).Select(e => 9999 - e).ToList());
    }
}

static class Locks
{
    public static void DoStuff(List<int> blah)
    {
        try
        {
            lock (blah)
            {
                for (var i = 0; i < blah.Count; i++)
                {
                    blah[i] = 1000 / blah[i];
                }
            }
        }
        catch (DivideByZeroException e)
        {
            Trace.WriteLine("Exception - divided by zero");
        }
    }
}

【讨论】:

    猜你喜欢
    • 2020-02-05
    • 2011-11-07
    • 1970-01-01
    • 2014-03-02
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多