32位环境下{64}的64位变量的原子增量

时间:2016-06-01 07:21:14

标签: c# .net interlocked-increment

another question写了一些有趣的答案,现在我无法理解Interlocked.Increment(ref long value)如何在32位系统上运行。让我解释一下。

在编译32位环境时,原生InterlockedIncrement64现在不可用了,好吧,这是有道理的,因为在.NET中你可以根据需要对齐内存,可以从托管<来调用它/ em>然后他们放弃了它。

在.NET中,我们可以通过引用64位变量来调用Interlocked.Increment(),我们对其对齐没有任何约束(例如在结构中,我们也可以使用{{ 1}}和FieldOffset)但文档没有提到任何限制(AFAIK)。这很神奇,它有效!

Hans Passant指出StructLayout是JIT编译器识别的特殊方法,它将发出COMInterlocked::ExchangeAdd64()的调用,然后调用FastInterlockExchangeAddLong InterlockedExchangeAdd64的一个宏,它共享InterlockedIncrement64的相同限制

现在我很困惑。

忘记一秒钟的托管环境,然后回到本地。为什么Interlocked.Increment()能够正常工作,InterlockedIncrement64呢? InterlockedExchangeAdd64是一个宏,如果内在函数不可用且InterlockedIncrement64有效,那么它可以实现为对InterlockedExchangeAdd64的调用......

让我们回到托管:如何在32位系统上实现原子64位增量?我猜句子&#34;这个函数对于调用其他互锁函数是原子 &#34; 很重要但我还是没有看到任何代码(感谢Hans指出更深入的实施)去做。当内在函数不可用时,让我们从WinBase.h中选择InterlockedExchangeAdd64实现:

InterlockedExchangedAdd64

如何读/写原子?

1 个答案:

答案 0 :(得分:9)

您必须继续跟踪,InterlockedExchangeAdd64()将您带到WinNt.h SDK头文件。您将在哪里看到它的许多版本,具体取决于目标架构。

这通常会崩溃:

#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64

它将buck传递给编译器内部函数,在vc / include / intrin.h中声明并由编译器的后端实现。

或者换句话说,CLR的不同构建将具有不同的实现。多年来已经有很多,x86,x64,Itanium,ARM,ARM8,PowerPC脱颖而出,我确实错过了一些用于启动WindowsCE的苹果之前,而苹果公司却无关紧要。对于x86,这最终由LOCK CMPXCHNG8B处理,LOCK CMPXCHNG8B是一种专用处理器指令,可以处理未对齐的64位变量。我没有硬件可以看到它在其他32位处理器上的样子。

请记住,托管代码的目标体系结构在编译时没有被确定。它是在运行时使MSIL适应目标的抖动。这对C ++ / CLI项目来说并不那么重要,因为如果使用/ clr而不是/ clr:pure进行编译,通常必须选择一个目标,并且只有x86和x64可以工作。但无论如何管道都已到位,所以宏观并不是非常有用。