2012-10-13 35 views
7

考慮讓currentPrice100之間的較多的以下兩種方式...三進制運算符(?:)線程在C#中安全嗎?

int price = currentPrice > 100 ? currentPrice : 100 

int price = Math.Max(currentPrice, 100) 

我提出這個問題,因爲我想在currentPrice變量可以被其他線程編輯的背景。

在第一種情況下...... price可能獲得的值低於100

我正在考慮以下幾點:

if (currentPrice > 100) { 
    //currentPrice is edited here. 
    price = currentPrice; 
} 

回答

8

它不是線程安全的。

?:只是快捷方式正常if,所以你if樣品相當於一個? - 你可以得到價格低於100,如果有這樣的代碼外沒有鎖定。

+0

相反的答案在幾分鐘內? :D – dotNETbeginner

+0

@dotNETbeginner :)很好的觀察。當我讀到我的第一個答案時,我也想給我-10。 –

3

理論上,currentPrice被讀取兩次。一次用於比較,一次用於分配。

實際上,編譯器可能會緩存對變量的訪問。我不知道C#,但在C++在x86:

MOV AX, [currentPrice] 
MOV BX, 100 ;cache the immediate 
CMP AX, BX 
JLE $1  ;if(currentPrice > 100){ 
MOV AX, BX 
$1:   ;} 
MOV [BP+price], AX ;price is on the stack. 

相同的負載,優化一次發生在Java字節碼,除非currentPrice被聲明爲volatile。

所以,從理論上講,它可能會發生。在實踐中,在大多數平臺上,它不會,但你不能指望這一點。

3

不是C#的專家,但即使var ++不是線程保存,因爲可能會轉換爲從彙編中的寄存器讀取/寫入。

三元運算符要複雜得多。它有3個部分,而每個部分可以無限大(例如呼叫某個功能)。因此,很容易得出三元運算符不是線程安全的結論。

+1

+1;我擔心x86不會讓你'INC'提供一個內存位置,所以它將被轉換爲註冊表/增量/移動到內存組合。 –

1

正如其他人所說,它可能被緩存,但語言並不需要它。

如果您需要無鎖定線程安全分配,則可以使用Interlocked.CompareExchange。但考慮到這個例子,我會選擇更粗粒度的鎖定策略。