Thursday, March 23, 2006

Singleton Pattern in Java

It is an interesting fact that people still consider double checked locking as a valid and the best way to implement Singletons in Java. A recent discussion with one of my peers brought this to my notice and hence I take this chance to describe the different implementations of singletons in Java and their drawbacks (or point to the right resources).
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.

1 comment:

  1. Your example will not compile:
    private static class Singleton{
    I suppose you meant:
    public class Singleton{

    ReplyDelete