Since synchronizing a method could in some extreme cases decrease performance by a factor of 100 or higher,[5] the overhead of acquiring and releasing a lock every time this method is called seems unnecessary: once the initialization has been completed, acquiring and releasing the locks would appear unnecessary.
Many programmers, including the authors of the double-checked locking design pattern, have attempted to optimize this situation in the following manner: Intuitively, this algorithm is an efficient solution to the problem.
Depending on the compiler, the interleaving of threads by the scheduler and the nature of other concurrent system activity, failures resulting from an incorrect implementation of double-checked locking may only occur intermittently.
For the singleton pattern, double-checked locking is not needed: If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.C++11 and beyond also provide a built-in double-checked locking pattern in the form of std::once_flag and std::call_once: If one truly wishes to use the double-checked idiom instead of the trivially working example above (for instance because Visual Studio before the 2015 release did not implement the C++11 standard's language about concurrent initialization quoted above [7] ), one needs to use acquire and release fences:[8] pthread_once() must be used to initialize library (or sub-module) code when its API does not have a dedicated initialization procedure required to be called in single-threaded mode.
[10] If the helper object is static (one per class loader), an alternative is the initialization-on-demand holder idiom[11] (See Listing 16.6[12] from the previously cited text.)
Semantics of final field in Java 5 can be employed to safely publish the helper object without using volatile:[13] The local variable tempWrapper is required for correctness: simply using helperWrapper for both null checks and the return statement could fail due to read reordering allowed under the Java Memory Model.