“不可变的字符串是线程安全的”是什么意思

时间:2013-09-29 16:22:14

标签: c# thread-safety immutability

我最近开始阅读C#中的可变和不可变对象,并且我发现无论我在哪里读取的常量是帽子是不可变的,当用作哈希表中的键时,使得线程安全且有用但是我不理解的是至于这个概念虽然我们无法改变我们可以改变参考的内容,但是:

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

虽然这里s的引用改为“Bye”,但主要的是s的内容(或者更确切地说是指向的内容)已经改变了,并且从编程的角度来看是相同的,所以如果字符串被更改,这如何使特定函数线程安全或可用于哈希表?

2 个答案:

答案 0 :(得分:2)

简单。如果要将s传递给在不同线程上运行的代码,则此代码将在传递参数时接收s指向的字符串。与.net中的所有字符串一样,它不会随着时间的推移而发生变化,因此您的线程代码不需要考虑您可以将s重新分配给不同的值。

如果您指定"再见"到s,原始字符串存在(直到收集垃圾),变量s指向新字符串。

在字典中,它略有不同。如果以一种哈希码更改的方式更改可变密钥,则字典将无法找到密钥:哈希码用于搜索索引,如果哈希码随时间变化,字典将找不到正确的记录。所以这并不是真正需要不变性,但不变性将确保一致的哈希码计算。

不变性对你有什么作用,它能够将对象视为值类型(如int),这通常更容易推理。

答案 1 :(得分:0)

在您的示例中,s被重新分配以引用不同的string对象(“Bye”),但s之前引用的对象(“Hi”)未更改。其他任何引用字符串“Hi”(另一个线程,Dictionary等)的内容都不会受到影响。正如您所提到的,string是不可变的 - 它的内容一旦创建就无法更改。例如,如果您将一个string附加到另一个string,则会获得一个新的string对象。两个原始string对象保持不变。这使得s线程安全,并且适合在哈希表中使用。

引用{{1}} 不是线程安全的 - 为了确保在使用引用时线程安全,您需要锁定引用赋值以确保一个线程当另一个线程正在写入时,它没有尝试从引用中读取。