一个非常简单的程序
private readonly string _data1;
private readonly int _data2;
private readonly MyAnotherClass _data3;
public MyClass(string data1, int data2, MyAnotherClass data3)
{
_data1 = data1;
_data2 = data2;
_data3 = data3;
}
_data1, _data2 and _data3
线程是否安全?
答案 0 :(得分:6)
只读变量可以在访问之前进行初始化。在完全分配对象之前,在构造对象期间分配初始值。
将变量初始值设定项转换为赋值语句,并在调用基类实例构造函数之前执行这些赋值语句。此排序可确保所有实例字段在执行有权访问该实例的任何语句之前由其变量初始化程序初始化。
参考:C#Spec,10.11.3构造函数执行(强调我的)
对只读字段的赋值只能作为字段声明的一部分或在同一类的构造函数中出现
参考:C#Spec,1.6.5字段
因此,该值将在任何线程可用之前设置,并且不会更改,因此它是线程安全的。
答案 1 :(得分:3)
是的,这是因为一旦构建了类,没有软件可以改变它们。
修改强>
虽然数据字段是线程安全的,但_data3的内容不是线程安全的。不同的线程可以“同时”修改_data3。
答案 2 :(得分:1)
Joh Skeets在Is a readonly field in C# thread safe?的回答给出了大部分答案 - 对于不可变类型(如int
/ string
),它是线程安全的。
如果自定义类型不是不可变引用,则引用本身将是线程安全的,但readonly
不保证对象内容的任何内容。因此_data3
对象的所有属性都需要具有自定义线程安全保护。
答案 3 :(得分:0)
只要你以后不改变它们,是的,它们就是。
编辑:
class Class1
{
readonly string bigbuddy;
public Class1()
{
bigbuddy = "1";
Thread thread1 = new Thread(SomeThread);
thread1.Start(this);
Thread.Sleep(1000);
bigbuddy = "2";
Thread thread2 = new Thread(SomeThread);
thread2.Start(this);
}
public void SomeThread(object state) {
Class1 class1 = (Class1)state;
Debug.WriteLine(class1.bigbuddy);
}
}
使用:
Class1 asd = new Class1();
输出:
1
The thread '<No Name>' (0xe0c) has exited with code 0 (0x0).
2
The thread '<No Name>' (0x129c) has exited with code 0 (0x0).