There are various EnsureInitialized overloads. Some accept a synclock object (which may be null and will be created by the EnsureInitialized method). Others do not have a synclock parameter as a parameter. All EnsureInitialized guarantees that if two (or more) different threads are called at the same time while the object is not initialized, the two threads will get a reference back to the same object. So:
Expensive _expensive; // On thread 1 LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive()); // On thread 2 LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());
the _expensive object that will be viewed by two threads will be the same.
The only problem is that new Expensive() could be called twice (once per thread, so in a multi-threaded race it could be called even more).
If you do not want this, use synclock overload:
Expensive _expensive; object _sync = null; bool _useless; // On thread 1 LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive()); // On thread 2 LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());
Now new Expensive() will be called only once, for each possible combination of two (or more) threads.
source share