2016-03-13 3 views
2

У меня создалось впечатление, что статическая инициализация по потоку по умолчанию. Это верно? Также рассмотрим приведенный ниже пример одноэлементного рисунка.Безопасность потоков в статических методах и переменных

public sealed class SingletonDemo 
{ 
    private static readonly SingletonDemo instance = new SingletonDemo();  
    private SingletonDemo() 
    {} 
    public static SingletonDemo Instance 
    { 
     get 
     { 
      return instance; 
     } 
    } 
} 

Является ли выше пример безопасной? Если да, то почему? Если нет, то почему?

+0

Смотрите также: [Jon тарелочкам: Реализация паттерна Singleton в C#] (http://csharpindepth.com/Articles/General/Singleton .aspx). Таким образом, в вашем коде все, что вам нужно добавить, это пустой статический конструктор ('static SingletonDemo() {}'), чтобы иметь «четвертую версию», которая была бы потокобезопасной. – Corak

+0

Thnx Corak для комментария, однако я думаю, что добавление статического конструктора принесет лень, и мне любопытно для безопасности потока. –

ответ

3

У меня создалось впечатление, что статическая инициализация по потоку по умолчанию. Это верно?

Да, с точки зрения инициализации - если вы не используете отражения для вызова типа инициализатору снова, и т.д. Конечно, может затем быть несколько потоков, обращающиеся к синглтон в то время, так что вам нужно, чтобы убедиться, что instance пользователей потокобезопасны.

Обратите внимание, что с C# 6, код может быть упрощен до:

правил инициализации
public sealed class SingletonDemo 
{ 
    public static SingletonDemo Instance { get; } = new SingletonDemo();  
    private SingletonDemo() {} 
} 

типа CLR гарантировать, что:

  • типа только инициализируется один раз
  • В то время как тип инициализируется в одном потоке, другие потоки пытаются получить к нему блок
  • После завершения инициализации по типу есть барьер памяти. читает доступ к переменной после инициализации типа завершения появится правильное значение

с кодом, как это, лень не гарантировала - другими словами, SingletonDemo может быть инициализирован, даже если он никогда не использовал (например, потому что метод называется который условно использует его, но условие не попало). Для того, чтобы сделать его полностью ленивы, вы можете либо использовать Lazy<T> или статический инициализатор:

public sealed class SingletonDemo 
{ 
    public static SingletonDemo Instance { get; } = new SingletonDemo();  
    private SingletonDemo() {} 
    private static SingletonDemo() {} 
} 
+0

Thnx Jon Skeet для ответа, но один вопрос по-прежнему бросает мой взгляд, что добавление статического конструктора для лени или безопасности потоков? поскольку оба являются независимыми вещами. –

+0

Итак, точка инициализации статического поля может варьироваться в зависимости от того, имеет ли тип статический конструктор или нет? * Редактировать *: Нашел ответ в вашей статье: «Статические конструкторы в C# заданы для выполнения только при создании экземпляра класса или упоминании статического члена». – Douglas

+1

@ Дуглас: Да - см. Http://pobox.com/~skeet/csharp/beforefieldinit.html –

Смежные вопросы