我正在测试Interlocked.Incrementlock在计算机体系结构上的行为,因为我在this article中阅读了以下几行。


  正如用Interlocked.Increment重写的那样,该方法至少在某些体系结构上应该执行得更快。


使用以下代码,我深信值得检查项目中的锁。

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。但是,我惊讶地发现,以释放模式运行此代码仅将Interlocked的值提高到大约0.7s,并且锁定时间保持不变。这是为什么?在释放模式下没有锁定时,如何优化互锁?

最佳答案

您必须查看生成的机器代码才能看到区别,即Debug + Windows + Disassembly。 Interlocked.Increment()调用的调试版本:

   00FC27AD  call        7327A810


发布版本:

   025F279D  lock inc    dword ptr [ebp-24h]


换句话说,抖动优化器在Release版本中变得非常聪明,并将对辅助函数的调用替换为一条机器指令。

优化并没有比这更好。不能将相同的优化应用于lock语句下面的Monitor.Enter()方法调用,它是CLR中实现的一个相当重要的函数,不能被内联。除了Interlocked.Increment()之外,它还执行许多其他操作,当线程在尝试获取监视器时受阻并维护等待线程的队列时,它允许操作系统重新调度。这对于确保良好的并发性非常重要,只是在测试代码中没有,因为锁是完全没有争议的。提防那些不能近似实际使用情况的综合基准。

关于c# - 互锁调试与 Release模式下的增量与锁定,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20730209/

10-09 07:29