dagblog.
← Archive

The Singleton and the problem of double-checked locking


If you’ve ever used the Singleton design pattern in a
 multithreaded environment, you’ve probably run into the problem of ensuring that the
 Singleton is unique, or more specifically, synchronizing the method that returns its instance.
 Synchronizing the entire method that returns the instance isn’t worth it because 
 the threads hold one another up.

Some resources therefore describe a technique called double-checked locking,
 which looks like this:

.
.
.
public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

The technique synchronizes only 
 the creation of the Singleton instance, and does so only if
 the Singleton is uninitialized (singleton == null)
 inside the synchronized block.

This code is good in theory but unusable in practice! The culprit is the Java memory
 model, which allows out-of-order writes. Essentially,
 the object reference can be something other than null (memory has already been allocated on the heap, with a pointer on the
 stack) while the object is still being initialized and its constructor is still running. The out-of-order write is introduced
 by the JIT compiler.

There are several possible solutions, each with pros and cons. For instance, you can use a static class variable
 or a volatile variable, for which the JIT compiler must not reorder writes.
 Peter Haggar explains the problem further 
 in his article Double-checked locking and the Singleton pattern
 . So does a team of experts: 
 David Bacon, Joshua Bloch, Jeff Bogda, Cliff Click, Paul Haahr, Doug Lea, Tom May, Jan-Willem Maessen, John D. Mitchell, Kelvin Nilsen, Bill Pugh, Emin Gun Sirer
 in their article The "Double-Checked Locking is Broken" Declaration

Medium version

Related articles

Related CZ Podcast episodes