День 2464. #ЗаметкиНаПолях****Потокобезопасная Инициализация с Помощью LazyInitializer Хотя Lazy является основным решением для ленивой инициализации в .NET, существует менее известная альтернатива, которая может быть более эффективной в некоторых сценариях: LazyInitializer.EnsureInitialized.
Этот статический метод обеспечивает потокобезопасную инициализацию с рядом ключевых характеристик:
- Только ссылочные типы: работает только с классами, но не со значениями.
- Обнаружение на основе NULL: использует значение NULL для определения необходимости инициализации.
- Эффективное использование памяти по сравнению с System.Lazy: не требуется дополнительный объект-обёртка.
Метод предлагает несколько перегрузок для различных сценариев: `Sample? _instance = null;
// Инициализация через конструктор по умолчанию var instance = LazyInitializer.EnsureInitialized(ref _instance);
// Фабричный метод var instance = LazyInitializer.EnsureInitialized( ref _instance, () => new Sample() );
// Фабричный метод вызывается 1 раз, даже если нескольким потокам требуется инициализация var syncLock = new object(); var instance = LazyInitializer.EnsureInitialized( ref _instance, ref syncLock, () => new Sample() );
Замечания по потокобезопасности По умолчанию LazyInitializer.EnsureInitialized ведёт себя как LazyThreadSafetyMode.PublicationOnly: Несколько потоков могут создавать экземпляры одновременно. Сохраняется только первое успешное назначение. Остальные экземпляры отбрасываются. Для строгой потокобезопасности используйте перегрузку с блокировкой синхронизации, чтобы гарантировать, что фабричный метод будет выполнен только один раз.
Внутренняя реализация этого аналогична следующему коду: `var instance = Volatile.Read(ref _instance) ?? Interlocked.CompareExchange( ref _instance, new Sample(), null);
Преимущества Главное преимущество перед Lazy — вместо хранения объекта-обёртки Lazy вы напрямую используете целевой экземпляр. Также это снижает затраты памяти, экономя одно поле на каждое лениво инициализированное значение.
Источник: *https://www.meziantou.net/thread-safe-initialization-with-lazyinitializer.htm*``