如何避免由于锁定代码而导致的减速

本文关键字:代码 何避免 于锁定 锁定 | 更新日期: 2023-09-27 18:12:28

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

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;
}

这段代码在我的机器上运行大约1300ms。如果我们移除锁块(但保留其主体),我们将获得750ms。几乎是双重的,即使代码从来没有运行过!

当然这段代码什么也不做。我注意到它,而在一个类中添加一些延迟初始化,其中代码检查对象是否初始化,如果没有初始化它。问题是初始化是锁定的,甚至在第一次调用之后也会减慢所有操作的速度。

我的问题是:

    为什么会发生这种情况?
  1. 如何避免减速

如何避免由于锁定代码而导致的减速

关于为什么会发生这种情况,在评论中已经讨论过了:这是由于lock生成的try ... finally的初始化。


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

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

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

编辑:我的测试代码(运行比没有锁的代码慢一点)实际上是在静态方法上,似乎当代码"在"对象内部运行时,时间是相同的。