我正在测试Interlocked.Increment
和lock
在我的计算机体系结构上的行为,因为我阅读了本文中的以下几行。
用Interlocked重写。增量,该方法应该执行得更快,至少在某些架构上是这样。
使用以下代码,我确信在我的项目中检查锁是值得的。
var watch = new Stopwatch();
var locker = new object();
int counter = 0;
watch.Start();
for (int i = 0; i < 100000000; i++)
{
lock (locker)
{
counter++;
}
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
watch.Reset();
counter = 0;
watch.Start();
for (int i = 0; i < 100000000; i++)
{
Interlocked.Increment(ref counter);
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds);
我得到了稳定的结果,锁定的近似值2.4s,联锁的近似值1.2s.7s,并且锁定时间保持不变。为什么?当处于解锁模式时,互锁是如何优化的?
您必须查看生成的机器代码才能看到差异,调试+Windows+反汇编。Interlocked的调试内部版本。Increment()调用:
00FC27AD call 7327A810
发布版本:
025F279D lock inc dword ptr [ebp-24h]
换句话说,抖动优化器在Release构建中变得非常聪明,并将对助手函数的调用替换为单个机器指令。
优化再好不过了。相同的优化不能应用于监视器。Enter()方法调用,它位于lock语句下面,是一个在CLR中实现的非常重要的函数,不能内联。除了Interlocked之外,它还能做很多事情。Increment(),它允许操作系统在线程阻止获取监视器时重新调度,并维护一个等待线程队列。这对于确保良好的并发性非常重要,只是在测试代码中不重要,因为锁是完全无争用的。注意那些与实际使用情况不近似的合成基准。