2013-09-29 53 views
5

我最近開始閱讀C#中的可變和不可變對象,並且我發現無論哪裏我閱讀的地方是帽子不可變使得事物線程安全且用作鍵時很有用在哈希表,但我不明白的是儘可能的理念去,雖然我們不能改變的內容,我們可以改變爲參考:這是什麼意思是「不可變的字符串是線程安全的」

string s = "Hi"; 
s = "Bye"; 

雖然這裏S的引用更改爲「再見」,但主問題在於s的內容(或者它指向的內容)已經發生了變化,並且從編程的角度來看它是相同的,那麼如果字符串被改變,這會如何使特定的函數線程安全或可用於散列表? ?

+0

看看http://stackoverflow.com/questions/2365272/why-net-string-is-immutable –

+0

@SonerGönül:閱讀....不完全揭示事情我' m詢問... –

回答

0

在您的示例中,s被重新分配以引用不同的string對象(「Bye」),但s先前引用的對象(「Hi」)未發生更改。其他任何引用字符串「Hi」(另一個線程,Dictionary等)的內容都將不受影響。正如你所提到的,string是不可變的 - 它的內容一旦創建就無法更改。例如,如果將另一個string附加到另一個,則會得到一個新的string對象。兩個原始的string對象保持不變。這是什麼讓string線程安全,並適合在散列表中使用。

參考s不是線程安全的 - 使用時的參考,保證線程安全,你需要把鎖圍繞基準分配,以確保一個線程不嘗試從讀取而另一個線程正在寫入它。

+0

「對字符串」Hi「(另一個線程,字典等)的引用的其他任何內容都將不受影響」 - 在這種情況下原始字符串不會用於GC嗎?如果它用於GC,請執行線程或字典分解....我的意思是會發生什麼?它在那種情況下指的是什麼?我的第二個評論jdv-Jan de Vaan上面有關字典也適用於這裏......在這種情況下會發生什麼? –

2

簡單。如果您要將s傳遞給在不同線程上運行的代碼,則此代碼將在參數傳遞時接收由s指向的字符串。與.net中的所有字符串一樣,它不會隨着時間而改變,因此您的線程代碼無需考慮您可以將s重新指定爲不同的值。

如果您爲s指定了「Bye」,則原始字符串將保留(直到其垃圾收集爲止),並且變量s指向一個新字符串。

在詞典中,它略有不同。如果您更改可變鍵的方式使其哈希碼更改,字典將無法找到該鍵:哈希碼用於在索引中進行搜索,並且如果哈希碼隨時間變化,字典將無法找到正確的記錄。所以這並不真正需要不變性,但不變性將確保hashcode的一致性計算。

對你而言,什麼是不變性,它能夠將對象想象爲一個值類型(比如int),這通常更容易推理。

+0

好吧......但告訴我,這假設該字符串是可變的...如果我將它作爲變量傳遞給運行在不同線程上的代碼..它會讓我通過的版本,並將與該數據,即使我以後改變它......對嗎? –

+0

也在詞典中例如你是說如果哈希值會發生變化,那麼將不會找到密鑰,但不會發生與不可變字符串相同的情況?我改變了它引用的數據,所以即使字符串在GC的內存中它指向一個不包含該數據的變量... –

+0

至於你的第一個評論:如果字符串是可變的,那麼可以改變一個你將它傳遞給另一個線程後,該線程可以看到更改。 – 2013-09-30 08:00:59