c# - Interlocked.Increment vs lock in debug vs release mode

标签 c# locking interlocked release-mode debug-mode

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

As rewritten with Interlocked.Increment, the method should execute faster, at least on some architectures.

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

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

最佳答案

您必须查看生成的机器代码以了解差异,Debug + Windows + Disassembly。 Interlocked.Increment() 调用的调试构建版本:

   00FC27AD  call        7327A810 

发布构建版本:

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

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

没有比这更好的优化了。相同的优化不能应用于 lock 语句下的 Monitor.Enter() 方法调用,它是在 CLR 中实现的一个非常重要的函数,不能内联。除了 Interlocked.Increment() 之外,它还做了很多事情,它允许操作系统在线程阻塞试图获取监视器时重新安排时间,并维护一个等待线程队列。这对于确保良好的并发性非常重要,只是不在您的测试代码中,因为锁是完全无竞争的。提防与实际使用情况不相符的综合基准。

关于c# - Interlocked.Increment vs lock in debug vs release mode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20730209/

相关文章:

c# - 仅当匹配文件存在时才移动文件

c# - 如何在 Visual Studio Code 调试期间传递 Azure KeyVault 的访问 token

svn - 除了从分支合并外,如何锁定 SVN 主干?

c# - Interlocked.Exchange 有多安全?

c# - Interlocked.CompareExchange 真的比简单的锁更快吗?

c# - onClick 和 onClientClick 事件一起使用。不适用于 Internet Explorer

c# - 如何从 Java 调用 .NET dll

c# - ReaderWriterLockSlim问题

sql-server - SQL Server 2012 : Running multiple UPDATE FROM SELECT on the same table simultaneously

c# - 我应该如何为争用最少的循环线程方案增加一个数字?