如何避免由于锁定代码而导致的减速
本文关键字:代码 何避免 于锁定 锁定 | 更新日期: 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。几乎是双重的,即使代码从来没有运行过!
当然这段代码什么也不做。我注意到它,而在一个类中添加一些延迟初始化,其中代码检查对象是否初始化,如果没有初始化它。问题是初始化是锁定的,甚至在第一次调用之后也会减慢所有操作的速度。
我的问题是:
- 为什么会发生这种情况?
- 如何避免减速
关于为什么会发生这种情况,在评论中已经讨论过了:这是由于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
编辑:我的测试代码(运行比没有锁的代码慢一点)实际上是在静态方法上,似乎当代码"在"对象内部运行时,时间是相同的。