2015-11-04 158 views
3

正如標題所說,可讀空布爾(bool?)在其讀/寫操作中被視爲原子嗎?我通過C#文檔搜索無濟於事。我知道只有某些原始類型保證執行讀/寫操作的原子性,而Bool是這些類型之一。當然,可空布爾類型是一個不同的故事;他們畢竟是物體,所以我會說,不,但...可以有人對這個問題有所瞭解嗎?是否爲可空布爾(bool?)被認爲是線程安全的?

回答

2

根據Nullable(T)

此類型的任何公共靜態成員是線程安全的。任何實例成員不保證是線程安全的。

+1

我假設問題是關於讀取/寫入'bool?'類型的變量,而不是對它們進行操作。 – Lee

+0

這並沒有真正解決賦值給一個可爲空的變量是否是原子的,儘管它確實意味着讀取Value或HasValue可能不是線程安全的。然而事情有點模糊,因爲可空對象具有特殊的運行時支持。在文檔中解釋該語句可能會非常棘手,因爲它是對任何未被設計爲線程安全的類的文檔附加的「全部捕獲」語句。 –

0

請注意,bool?實際上是一個Nullable<bool>在引擎蓋下;換句話說,這是一個結構。有一些特殊的運行時功能可以使它們的行爲看起來好像它們可以爲null,但最終它是一個帶有HasValue標誌和實際值的結構。

可能性非常好,它不提供原子讀/寫保證。理論上可以通過bool?來完成,因爲您可以將所有必要的數據放入單個機器字中,但對於一般可空實例來說,如果不進行可空訪問的某些同步進行烘焙,則不可行。


在一個側面說明,如果你需要這樣的事情,認爲這是一個bool?本質上只是一個三態值。你可以用一個枚舉有三個狀態來完成相同的結果,它提供了原子讀/寫保證(因爲默認情況下它只是一個int)。但是,通常,只使用同步基元比嘗試更安全正確實現無鎖代碼。

-2

理論上:就像你說的那樣,沒有保證。

實踐中:將它從一個變量複製到另一個變量是線程安全的。閱讀和寫作不是必然的。

這意味着:

shared = true; //avoid this 
bool result = shared.Value; //avoid this, too 

bool? local = true; 
shared = local; //threadsafe in practice 
[...] 
local = shared; //threadsafe in practice 

原因是,該指針尺寸或更小結構被複製作爲整體在一個步驟中由運行時,如果不存在類型轉換正在進行。

使值有用需要兩個步驟:1.檢查標誌,如果它爲空2.閱讀實際內容。這意味着它可能不是線程安全的。

您可能最好使用帶有常量的int來表示true,false和null。這也使您可以使用聯鎖功能(Exchange和CompareExchange可以非常方便!)

4

C#不保證讀取和寫入可爲空的變量是原子的。對於其操作被保證是原子的類型在本說明書中的第5.5節所定義(變量引用的原子):

讀取和下列數據類型的寫入是原子:布爾,焦炭,字節,爲sbyte,簡短,ushort,uint,int,float和引用類型。另外,在前面的列表中讀取和寫入帶有基礎類型的枚舉類型也是原子的。其他類型(包括long,ulong,double和decimal)以及用戶定義類型的讀取和寫入不保證是原子性的。除了爲此目的而設計的庫函數之外,不能保證原子讀取 - 修改 - 寫入,例如在遞增或遞減的情況下。

請注意,儘管可爲空,但它們不是引用類型。它們是具有運行時提供的特殊裝箱行爲的值類型。在規範的上下文中,如果需要特殊處理,它們被稱爲可爲空的值類型。