2010-07-26 63 views
1

在.Net中是否有等效的XADD命令?毕竟,这是锁定/检查关键部分锁定或确保多线程环境中精确增量的最有效方法。.Net等效于x86 ASM命令XADD

我翻看了IL操作码,但找不到相应的东西。

回答

3

在.NET中最接近的equivelent将使用Interlocked class。例如,您可以使用Interlocked.Add在多线程环境中进行安全,准确的增量。

+0

我试过了,它完美的工作,谢谢。 – IamIC 2010-07-27 10:52:46

1

看看Interlocked课,特别注意Interlocked.Add。以下是它在IL中的使用示例。

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 a, 
     [1] int32 b) 
    L_0000: ldc.i4.5 
    L_0001: stloc.0 
    L_0002: ldc.i4.7 
    L_0003: stloc.1 
    L_0004: ldloca.s a 
    L_0006: ldloc.1 
    L_0007: call int32 [mscorlib]System.Threading.Interlocked::Add(int32&, int32) 
    L_000c: pop 
    L_000d: ret 
} 
+0

完美!谢谢。 – IamIC 2010-07-27 10:51:31

7

获取锁比简单的CPU指令要多得多。试图获得它并没有得到它的代价非常高。记录在2000到10,000机器指令之间。线程上下文的数字越高,就切换到另一个进程中的线程,这需要重新加载虚拟内存页面转换表。

在多核CPU上有意义的一个非常常见的策略是spin-wait。代码进入一个严密的循环,严重烧毁CPU周期,试图获得锁。它在这个循环中花费的确切时间在技术上是一个可调项目,但在实践中没有太大的区别。

Anyhoo,它是CLR的工作,编译器是隐藏实现细节。一个这样做的核心类是Monitor类。例如,在C#中使用锁语句时,会使用它,编译器会自动将其转换为Monitor.Enter调用,自动生成try和finally块,finally块将执行Leave()方法。

这些方法的实现在CLR中。这里有相当多的代码,它所做的另一件事是处理“公平性”。它确保线程不会饿死,试图获取锁。该代码是用C++编写的,与原始CPU指令相差甚远。它最终归结为实现实际锁定的实际代码。是的,这是用汇编编写的,至少在CLR的共享源代码版本中。该代码住在PAL(平台适配层),它的x86版本是这样的:与锁前缀

FASTCALL_FUNC CompareExchangeMP,12 
     _ASSERT_ALIGNED_4_X86 ecx 
     mov  eax, [esp+4] ; Comparand 
    lock cmpxchg [ecx], edx 
     retn 4    ; result in EAX 
FASTCALL_ENDFUNC CompareExchangeMP 

的cmpxchng CPU指令实现锁典型的一个。加入:

FASTCALL_FUNC ExchangeAddUP,8 
     _ASSERT_ALIGNED_4_X86 ecx 
     xadd [ecx], edx  ; Add Value to Target 
     mov  eax, edx 
     retn 
FASTCALL_ENDFUNC ExchangeAddUP 

但是,这通常不用于锁定。如果您想自己查看,请下载SSCLI20源代码,并在clr \ src \ wm \ i386 \ asmhelpers.asm处查看。这是否实际用于CLR的当前装运版本是一个悬而未决的问题。它非常核心,所以有点可能。 Monitor方法实现位于clr \ vm \ syncblk.cpp,AwareLock类中。我很确定它的SSCLI20版本不是你机器上运行的版本,它们一直在修补“公平”算法。

+0

感谢您的详细解答,Hans :) – IamIC 2010-07-27 10:52:00