Thread Safe C # Singleton Pattern

У меня есть некоторые вопросы относительно шаблона singleton, как описано здесь: http://msdn.microsoft.com/en-us/library/ff650316.aspx

Следующий код является выпиской из статьи:

using System; public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } } } 

В частности, в приведенном выше примере необходимо ли сравнивать экземпляр с null в два раза до и после блокировки? Это необходимо? Почему бы не выполнить блокировку сначала и провести сравнение?

Есть ли проблема в упрощении следующего?

  public static Singleton Instance { get { lock (syncRoot) { if (instance == null) instance = new Singleton(); } return instance; } } 

Является ли выполнение блокировки дорогостоящим?

Выполнение блокировки ужасно дорого по сравнению с простым instance != null проверки указателя instance != null .

Образец, который вы видите здесь, называется двойной проверкой блокировки . Его цель состоит в том, чтобы избежать дорогостоящей операции блокировки, которая будет нужна только один раз (когда односторонний доступ к первому доступу). Реализация такова, потому что она также должна гарантировать, что при инициализации синглтона не будет ошибок, вызванных условиями гонки нитей.

Подумайте об этом так: голая null проверка (без lock ) гарантированно даст вам правильный полезный ответ, только когда этот ответ «да, объект уже построен». Но если ответ «еще не сконструирован», то у вас недостаточно информации, потому что то, что вы действительно хотели знать, это то, что он «еще не сконструирован, и ни один другой stream не собирается строить его в ближайшее время ». Таким образом, вы используете внешнюю проверку в качестве очень быстрого первоначального теста, и вы инициируете правильную, без ошибок, но «дорогостоящую» процедуру (блокировка, а затем проверка), только если ответ «нет».

Вышеприведенная реализация достаточно хороша для большинства случаев, но на данный момент неплохо пойти и прочитать статью Джона Скита о одиночных играх на C #, которая также оценивает другие альтернативы.

Ленивая версия:

 public sealed class Singleton { static readonly Lazy lazy = new Lazy(() => new Singleton()); private Singleton() { } public static Singleton Instance => lazy.Value; } 

Требуется .NET 4 и C # 6.0 (VS2015) или новее.

Выполнение блокировки: довольно дешево (еще дороже, чем нулевой тест).

Выполнение блокировки, когда другой stream имеет это: вы получаете стоимость того, что им еще нужно делать при блокировке, добавленной в свое время.

Выполнение блокировки, когда другой stream имеет ее, и на нее также ждут десятки других streamов: Crippling.

По соображениям производительности вы всегда хотите иметь блокировки, которые требуется другому streamу, в течение самого короткого периода времени.

Разумеется, легче рассуждать о «широких» замках, чем узких, поэтому стоит начать с них широким и оптимизировать по мере необходимости, но есть некоторые случаи, которые мы узнаем из опыта и знакомства, где более узкий подход к шаблону.

(Кстати, если вы можете просто использовать private static volatile Singleton instance = new Singleton() или если вы можете просто не использовать одиночные игры, но вместо этого использовать статический class, то оба лучше подходят для этих проблем).

Причина в производительности. Если instance != null (который всегда будет иметь место, за исключением самого первого раза), нет необходимости выполнять дорогостоящую lock : два streamа, обращающихся к инициализированному одноэлементному соединению одновременно, будут синхронизироваться неслучайно.

Почти в каждом случае (то есть: все случаи, кроме самых первых), instance не будет равен нулю. Приобретение блокировки является более дорогостоящим, чем простая проверка, поэтому проверка, когда значение instance перед блокировкой является хорошей и бесплатной оптимизацией.

Этот шаблон называется блокировкой с двойной проверкой: http://en.wikipedia.org/wiki/Double-checked_locking

Джеффри Рихтер рекомендует следующее:

 public sealed class Singleton { private static readonly Object s_lock = new Object(); private static Singleton instance = null; private Singleton() { } public static Singleton Instance { get { if(instance != null) return instance; Monitor.Enter(s_lock); Singleton temp = new Singleton(); Interlocked.Exchange(ref instance, temp); Monitor.Exit(s_lock); return instance; } } } 

Вы можете с нетерпением создать streamобезопасный экземпляр Singleton, в зависимости от потребностей вашего приложения, это краткий код, хотя я бы предпочел ленивую версию @ andasa.

 public sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton() { } public static Singleton Instance() { return instance; } } 
  • Каким образом реализация Майерсом Синглтона на самом деле является синглтон
  • Синглтон с аргументами в Java
  • Синглтон в iOS 5?
  • Зачем выбирать статический class по сравнению с одноэлементной реализацией?
  • Singleton class в java
  • Каков наилучший подход для использования Enum в качестве одноэлементной на Java?
  • Что такое синглтон в C #?
  • Одиночный class с несколькими различными загрузчиками classов
  • Как реализовать многопоточный безопасный синглтон в C ++ 11 без использования
  • Проблемы с шаблоном Singleton
  • Как насмехаться с classом одиночного Single Enum с использованием Mockito / Powermock?
  • Interesting Posts

    как установить ориентацию изображения камеры?

    Подтвердить ограничения валидации компонентов уровня classа в JSF

    Конвертер PDF в формате PDF

    Принудительный сценарий bash для выполнения до завершения, когда некоторые элементы могут

    Как установить короткую ссылку symlink на Sublime Text 3 в терминале?

    Как установить Citrix ICA Client (Receiver) 13 на 64-разрядную версию Debian?

    Как я могу отказаться от Windows 7 до Windows Vista?

    Открыть новое всплывающее окно без адресных баров в firefox & IE

    Может ли (a == 1 && a == 2 && a == 3) когда-либо оценивать значение true?

    Как записывать видео с фона приложения: Android

    jquery fancybox 2.0.3 – предотвратить закрытие клика за пределами fancybox

    Ubuntu – Обновление до 10.04 – общая файловая система с монтированием ошибок

    Могу ли я установить Windows 7 x64 на MacBook Air?

    Как я могу установить собственные закладки в PDF-файле?

    Как показать детали текущей строки из p: dataTable в диалоговом окне ap: и обновить после сохранения

    Давайте будем гением компьютера.