When we are writing code that sometimes requires some object to be created, and sometimes not, we can save some execution time by only creating this object when it is needed. This process-lazy initialization is explained in Chapter 2, Singleton, Dependency Injection, Lazy Initialization, and Object Pool. That chapter, however, only covered single-threaded applications.
To do lazy initialization properly in a multithreaded world, we need locking. And to do it correctly and fast, we need a double-checked locking pattern. This pattern can speed up any lock that is only acquired if some condition is met. It is also called test, lock, and test again.
For instance, when you are changing lanes in a car, you check the traffic around you first, then turn on your indicator, check the traffic again, and then change lane.
In the demonstration program DoubleCheckedLocking...