Singletons can be implemented in Java in multiple ways. Each implementation guarantees a single instance (not considering serialization and extension, which have to be handled anyway), but vary in thread safety.
SYNCHRONIZE GETINSTANCE METHOD
Implement a synchronized getInstance() method. This method can be seen in
listing 1. Though this method guarantees a singleton and is thread safe,
it comes with the overhead of synchronization. Each call to getInstance()
carries the overhead synchronization.
public class Singleton {
private static Singleton instance = null;
private Singleton() {
// Make it private to avoid instantiation.
}
public synchronized static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
Listing 1: Singleton implementation with synchronized getInstance()
DOUBLE CHECKED LOCKING
In order to minimize synchronization overhead, double checked locking method has
been suggested. This method can be seen in the listing 2. Here the a
synchronized block is entered only when
instance
is null, which occurs when the first thread (or set of threads simultaneously) enters the getInstance() method. Although this method is more efficient, it may fail to be thread-safe when used with an optimizing compiler, as described in Double checked locking and the Singleton Pattern. Many different variants of this implementation have been suggested and disproved. One of the variants (using volatile instance) of double checked locking implementation of the singleton pattern can be used successfully in Java 5 because of the changes made in JSR 133, but it does not add much to performance over the synchronized implementation. This is because, with the changes made to the Java memory model in JSR 133, the cost of using volatile
is comparable to that of synchronizing.class Singleton {
private static Singleton instance = null;
public Singleton getInstance() {
if (instance == null) {
synchronized {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
Listing 2: Singleton implementation with double checked locking.
USING STATIC VARIABLE INITIALIZATION
The best way to implement singletons in Java is to initialize the static
instance variable with it's declaration or initializing the instance variable from within a static initialization block. This implementation can be seen in listing 3.
private static class Singleton{
public static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
Listing 3: Singleton with static variable initialization.
This implementation is thread-safe because, the Java language specification (8.3.2 Initialization of fields) guarantees that the static member variables will be initialized exactly once.
If the declarator is for a class variable (that is, a static field), then the variable initializer is evaluated and the assignment performed exactly once, when the class is initialized.