簡體   English   中英

Interlocked.Exchange澄清

[英]Interlocked.Exchange clarification

我有一些簡單(希望)的問題,我一直無法找到答案 -

假設我有多個線程可以訪問的對象a,b。

Interlocked.Exchange(ref a, b)

如果'b'不是易變的,這個操作會不會這樣處理? 即它會從內存中獲取此變量的最新值嗎? 如果是這樣,那寫入是'原子'嗎? 據我所知,Interlocked.Exchange的主要目的是使用新寫入將原來的'a'值作為原子操作。 但我的主要困惑在於'b'實際寫入'a'的價值。

我的第二個問題與本文中的引用有關:

http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

“一個有趣的觀點是C#中的所有寫操作都是根據本文和此處記錄的內存模型進行的,並且也可能是這樣實現的.C#語言的ECMA規范實際上定義了一個較弱的模型,其中寫入默認情況下不是易失性的“。

這是真的? 如果是這樣,如果不關心'a'的先前值,是否有Interlocked.Exchange的目的? (與我的第一個例子有關)。 我沒有在StackOverflow上看到任何關於每個寫入易失性的文章或評論。 但是,我知道寫入是原子的。

編輯:如果我的第一個問題的答案是“b”不被視為易失性,而我的第二個問題的答案是寫入確實是不穩定的,那么跟進就是,什么時候是聯鎖的。如果我們不這樣做,則有用關心'a'的先前價值?

傳遞給Exchange的變量(或傳遞給任何方法的任何volatile變量)在傳遞時不會保留“volatile”...實際上不需要它是volatile (在方法調用期間)因為唯一的volatile確保編譯器不優化變量的使用(這通常意味着優化寫入寄存器,因此值只能由單個處理器“看到”)。 在x86 / x64以外的處理器上,這有時意味着保證獲取或釋放語義的指令。 .NET不使用寄存器進行參數傳遞,因此volatile不會影響傳遞的參數的“波動性”。 由於內存模型的可見性保證,它必須始終從內存中獲取最新值

RE問題2:引用是“真實的”,取決於字段的聲明,有可見性保證wrt字段; 但是沒有“volatile”字段訪問可以在某些使用階段被優化到寄存器中,可能隱藏來自其他處理器的某些寫入。

Interlocked交換使非原子的操作看起來是原子的。 交換本質上類似於:

var x = someVariable;
someVariable = y;

無論someVariable的類型如何,這都不可能是原子的。 Exchange使此操作成為原子。 這也是非原子類型的原子,如doublelong (32位)等。

Exchange使用這個原子的部分原因是使用內存柵欄 - 這使得寫入可見而不是重新排序,並且在內存柵欄之后的指令序列中讀取相同的內存地址。

如果您不關心“a”的先前值,為什么要使用Exchange 如果你不關心實際的“交換”,那么VolatileWrite似乎更合適。

或者,如果不需要“交換”,您可以編寫線程安全代碼來模擬“A = B”,如下所示:

Thread.MemoryBarrier();
A=B;

FWIW, Interlocked部分模擬了某些處理器中的比較和交換(CAS)指令。 這些指令允許您在一條指令中執行這兩項操作(使其成為原子)。 如果沒有像Interlocked這樣的東西,編譯器可能很難推斷出應該使用這些CAS指令之一。 此外, Interlocked在不支持這些CAS指令的處理器上提供原子使用(以及其他可能非原子指令,如inc和dec - 可能並非在所有處理器上都可用)

如果'b'不是易變的,這個操作會不會這樣處理?

b是共享變量時,我認為你不應該使用它。 這樣就消除了整個問題。 但Exchange總會使用Memorybarrier,所以答案可能是肯定的。

何時是interlocked.exhange有用,如果我們不關心'a'的先前值?

double的重載非常有用,因為寫入double不是原子的。 32位系統上的Int64也是如此。

但是對於原子類型的Exchange()重載,用例不太清楚。 我認為大多數算法都支持CompareExcange()

所以考慮一下原子Write()。

如果'b'不是易變的,這個操作會不會這樣處理?

是的,因為根據這個來源Interlocked類的所有方法都會生成隱式內存柵欄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM