Почему (или нет) установка полей в конструкторе безопасна для потоков?
Допустим, у вас есть простой класс, подобный этому:
class MyClass
{
private readonly int a;
private int b;
public MyClass(int a, int b) { this.a = a; this.b = b; }
public int A { get { return a; } }
public int B { get { return b; } }
}
Я мог бы использовать этот класс многопоточным способом:
MyClass value = null;
Task.Run(() => {
while (true) { value = new MyClass(1, 1); Thread.Sleep(10); }
});
while (true)
{
MyClass result = value;
if (result != null && (result.A != 1 || result.B != 1)) {
throw new Exception();
}
Thread.Sleep(10);
}
Мой вопрос: увижу ли я когда-нибудь этот (или другой подобный многопоточный код) исключение? Я часто вижу ссылку на тот факт, что энергонезависимые записи могут быть не сразу замечены другими потоками. Таким образом, кажется, что это может не получиться, потому что запись в поле значения может произойти до записи в a и b. Возможно ли это, или в модели памяти есть что-то, что делает этот (довольно распространенный) шаблон безопасным? Если так, то, что это? Имеет ли значение только для чтения? Было бы важно, если бы a и b были типом, который нельзя написать атомарно (например, пользовательская структура)?