Interlocked.Increment 到底在做什么?

What is Interlocked.Increment actually doing?

提问人:Maxim Gershkovich 提问时间:4/18/2011 最后编辑:JasonMArcherMaxim Gershkovich 更新时间:7/18/2015 访问量:7261

问:

Interlocked.Increment似乎是需要在多线程代码中执行的最标准/最简单的操作之一。

我假设该方法的功能是任何具有线程经验的人都可以复制的某种排序模式。

所以基本上我想知道的是,是否有人可以提供该方法在内部实际执行的确切副本(并解释其工作原理)?(我一直在寻找实际方法的来源,但找不到)Interlocked.Increment

C# 多线程 互锁

评论

0赞 ipavlu 11/1/2015
我不得不说,你的假设,它是某种模式,每个做多线程代码的人都会知道它很可爱,但最终是不真实的。不幸的是,我必须补充:)。根据我的经验,许多人认为联锁很奇怪,一般没有必要或更糟,根本不考虑它们,因为他们不知道联锁方法。

答:

1赞 vhallac 4/18/2011 #1

我希望它是 InterlockedIncrement64 Win32 API 调用的包装器。


编辑:我看到这是一个非常简短的回应。在此基础上构建一点:复制函数的功能很容易,但性能却不容易。大多数 CPU 中都有本机指令为您提供原子“互锁交换和添加”指令,因此您希望该指令用于实现您的函数,我希望从 C# 中实现此目的的最简单方法是进行 win32 API 调用。有关该主题的更多背景信息,请查看此白皮书

评论

1赞 David Heffernan 4/18/2011
互锁的 Win32 API 作为编译器内部函数实现
0赞 vhallac 4/18/2011
@David 64 位窗口为 True,但它们可用于 32 位窗口。无论如何,Brian 的答案已经通过检查 JIT 输出提供了答案,这表明代码直接发出必要的 x86 指令。
1赞 David Heffernan 4/18/2011
即使在 32 位中,它们也被实现为编译器内部函数。kernel32 提供了导出功能,但出于明显的性能原因,所有最近的编译器都使用内部函数
14赞 grzeg 4/18/2011 #2

根据Albahari先生的说法,它做了两件事:

  • 使操作系统和 VM 知道操作的原子性,因此,例如,对 32 位系统上的 64 位值的操作将是原子的
  • 生成对互锁变量的限制性重新排序和缓存full fence

看看那个链接 - 它给出了一些很好的例子。

评论

0赞 bestsss 4/18/2011
在 CAS 之后的 x86/64 上,您不需要额外的围栏。通常 impl 只是一个循环加载/增量/CAS(成功 CAS 时中断)
9赞 Brian Rasmussen 4/18/2011 #3

我假设它是一个实现细节,但查看它的一种方法是检查 JIT 编译的代码。请考虑以下示例。

private static int Value = 42;
public static void Foo() {
   Interlocked.Increment(ref Value);
}

在 x86 上,它会生成以下内容

lock inc dword <LOCATION>

修饰符锁定总线,以防止多个 CPU 更新同一数据位置。

在 x64 上,它生成

lock xadd dword ptr <LOCATION>,eax

评论

0赞 Nubok 11/22/2012
你能说出它在 x64 上使用“lock xadd”而不是“lock add”的原因吗?
2赞 supercat 2/12/2013
如何处理返回值?lock inc dword <location>