Есть ли вероятность, что в то время, как поток ссылается на MyFoo.Foo, другой поток, ссылающийся на него, получит незавершенные или неинициализированные данные обратно, так как InitFoo () еще не завершен?
Нет.Инициализация типа является поточно-ориентированной:
- Никакие другие потоки не могут использовать ваш тип, пока он инициализируется другим потоком
- Все записи в память, выполняемые потоком инициализации, становятся видимыми длядругие потоки, когда инициализация была выполнена
Есть одна складка, которая заключается в том, что если тот же поток, который инициализирует MyFoo
, заканчивает чтение MyFoo._foo
до того, как завершит инициализацию, чтовызовет проблему.Это может быть особенно неудобно для диагностики, если есть типы, которые зависят друг от друга для инициализации в цикле.
Вот пример с двумя инициализаторами типов, каждый из которых использует значение от другого.У них обоих есть статические конструкторы, чтобы сделать поведение детерминированным.(Правила того, когда типы инициализируются, зависят от того, имеют ли они статические конструкторы.)
using System;
public class Program
{
public static void Main(string[] args)
{
// Determine which type to initialize first based on whether there
// are any command line arguemnts.
if (args.Length > 0)
{
Class2.DoNothing();
}
Console.WriteLine($"Class1.Value1: {Class1.Value1}");
Console.WriteLine($"Class2.Value2: {Class2.Value2}");
}
}
public class Class1
{
public static readonly string Value1 =
$"When initializing Class1.Value1, Class2.Value2={Class2.Value2}";
static Class1() {}
}
public class Class2
{
public static readonly string Value2 =
$"When initializing Class2.Value2, Class2.Value2={Class1.Value1}";
static Class2() {}
public static void DoNothing() {}
}
При запуске без каких-либо аргументов командной строки Class1
начинает инициализацию первой, что, в свою очередь, инициализирует Class2
:
Class1.Value1: When initializing Class1.Value1, Class2.Value2=When initializing Class2.Value2, Class2.Value2=
Class2.Value2: When initializing Class2.Value2, Class2.Value2=
С любым аргументом командной строки мы сначала инициализируем Class2
, что, в свою очередь, инициализирует Class1
:
Class1.Value1: When initializing Class1.Value1, Class2.Value2=
Class2.Value2: When initializing Class2.Value2, Class2.Value2=When initializing Class1.Value1, Class2.Value2=