2010-07-26 82 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