Я часто слышал, что в модели памяти .NET 2.0 записи всегда используют заборные блоки. Это правда? Означает ли это, что даже без явных барьеров памяти или блокировок невозможно наблюдать частично сконструированный объект (только для ссылочных типов) в потоке, отличном от того, на котором он создан? Я, очевидно, исключаю случаи, когда конструктор теряет ссылку this
.
Например, допустим, что у нас был неизменный ссылочный тип:
public class Person
{
public string Name { get; private set; }
public int Age { get; private set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
Можно ли со следующим кодом наблюдать любой выход, отличный от "John 20" и "Jack 21", например "null 20" или "Jack 0"?
// We could make this volatile to freshen the read, but I don't want
// to complicate the core of the question.
private Person person;
private void Thread1()
{
while (true)
{
var personCopy = person;
if (personCopy != null)
Console.WriteLine(personCopy.Name + " " + personCopy.Age);
}
}
private void Thread2()
{
var random = new Random();
while (true)
{
person = random.Next(2) == 0
? new Person("John", 20)
: new Person("Jack", 21);
}
}
Означает ли это, что я могу сделать все общие поля с глубоко неизменяемыми ссылочными типами volatile
и (в большинстве случаев) просто работать с моей работой?