roland luo
roland luo

Reputation: 1631

Two way of implementing singleton with thread safe lazy initialization

Static method and variable:

public class Singleton{

    private static Singleton singleton = null;

    private Singleton(){
    }

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

Second after Java 1.5

public class Singleton{

    private static volatile Singleton singleton = null;

    private Singleton(){
    }

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

So what's the pros and cons for these two thread safe code and when should we use which?

Upvotes: 1

Views: 690

Answers (6)

The first one is not thread safe. It would be thread safe if getInstance was synchronized.

If you need thread safety, use the second one.

There is a much simpler third way though, which is slightly different (the Singleton gets created at a different time):

public class Singleton{

    private static final Singleton singleton = new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
        return singleton;
    }
}

Upvotes: -1

enterbios
enterbios

Reputation: 1757

The second one 'double checked' singleton is faster because it don't need to acquire lock whenever you ask for instance (despite first calls). Anyway best way to control life cycles of your objects is using dependency injection.

Upvotes: 0

nosid
nosid

Reputation: 50034

Both implementations are thread-safe and valid.

The former is shorter. It is more readable and maintainable.

The latter is faster, and it's also faster than most people think. Depending on the implementation of the Java VM, reading a volatile variable is as fast as reading a non-volatile variable on x86. That means the overhead occurs only during the initialaztion. But as soon as the singleton has been initialized, there is no overhead at all.

If performance is really an issue, you should use the latter. Otherwise use the former, because the need for readability and maintainability is often underestimated.

Upvotes: 3

Santosh
Santosh

Reputation: 17893

Both examples are of lazy initialization of singleton i.e. you initialize the singleton at the moment you need.The second example is an example of double checked locking which is primarily aimed at thread-safe.

Upvotes: 0

Matt
Matt

Reputation: 637

The safest way to go about doing a thread-safe singleton is via the initialisation on demand holder idiom:

public class Foo {
    private Foo() {}
    private static class Holder {
        private static final Foo INSTANCE = new Foo();
    }
    public static Foo getInstance() {
        return Holder.INSTANCE;
    }
}

This works in Java versions that didn't properly support the volatile keyword. The neat thing about this pattern is that it uses implicit locking only on the first access of getInstance. After that, access is unsynchronized. This is due to a fun little quirk of memory management and static loading in Java.

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533492

The second is thread safe but the following is much simpler, and faster as it doesn't require a synchronized block.

public enum Singleton {
    INSTANCE;
    // define fields and methods here.
}

to access

Singleton.INSTANCE.method();

Note: an enum can implement an interface if you need.

Upvotes: 5

Related Questions