Does double checking blocking have some peculiar advantage over atomic operations?
(This answer only covers C #, I don't know what the Java memory model is.)
The fundamental difference is a potential race. If you have:
if (f == null) CompareExchange(ref f, FetchNewValue(), null)
then FetchNewValue () can be called arbitrarily many times for different threads. One of these topics wins the race. If FetchNewValue () is extremely expensive, and you want it to be called only once, then:
if (f == null) lock(whatever) if (f == null) f = FetchNewValue();
Ensures that FetchNewValue is called only once.
If I personally want to perform lazy initialization with a low lock, then I do what you offer: I use an interconnected operation and live with a rare race condition, when two threads start the initializer, and only one wins. If this is unacceptable, I use locks.
source share