2013-09-29 49 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