18

我想知道即使代码从未执行过,一段锁定的代码如何减慢我的代码速度。下面是一个例子:

public void Test_PerformanceUnit()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    Random r = new Random();
    for (int i = 0; i < 10000; i++)
    {
        testRand(r);
    }
    sw.Stop();
    Console.WriteLine(sw.ElapsedTicks);
}

public object testRand(Random r)
{
    if (r.Next(1) > 10)
    {
        lock(this) {
            return null;
        }
    }
    return r;
}

此代码在我的机器上运行约 1300 毫秒。如果我们移除锁块(但保留它的主体),我们得到 750 毫秒。几乎是两倍,即使代码从未运行过!

当然,这段代码什么也不做。我在一个类中添加一些惰性初始化时注意到了这一点,代码检查对象是否已初始化,如果没有初始化它。问题是初始化被锁定并且即使在第一次调用之后也会减慢一切。

我的问题是:

  1. 为什么会这样?
  2. 如何避免减速
4

1 回答 1

10

try ... finally关于它发生的原因,已经在评论中讨论过:这是由于lock.


为了避免这种减速,您可以将锁定特性提取到一个新方法中,这样只有在实际调用该方法时才会初始化锁定机制。

我用这个简单的代码试了一下:

public object testRand(Random r)
{
    if (r.Next(1) > 10)
    {
        return LockingFeature();
    }
    return r;
}

private object LockingFeature()
{
    lock (_lock)
    {
        return null;
    }
}

这是我的时间(以刻度为单位):

your code, no lock   : ~500
your code, with lock : ~1200
my code              : ~500

编辑:我的测试代码(运行速度比没有锁的代码慢一点)实际上是在静态方法上,看起来当代码在对象“内部”运行时,时间是相同的。我据此确定了时间。

于 2013-05-06T12:53:32.537 回答