javadesign-patternssynchronizationsingletonsynchronized

Can we avoid the use of Volatile in Singleton Pattern by making the getInstance() method synchronized in Java?


In most places, this is the implementation followed for Singleton Design Pattern.

It makes use of the keyword volatile to prevent the issue of partial object creation (establishes happens-before relation between reads and writes to instance).

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

I was wondering if we could avoid the usage of volatile by making the entire getInstance() method synchronized? If it does not work, how would the execution of both cases differ?


Solution

  • I was wondering if we could avoid the usage of volatile by making the entire getInstance() method synchronized? If it does not work, how would the execution of both cases differ?

    It's possible and makes the code simpler, but has implications.

    Example lazy-loaded Singleton using double-checked locking: https://github.com/iluwatar/java-design-patterns/blob/master/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java

    Example lazy-loaded Singleton using synchronized method: https://github.com/iluwatar/java-design-patterns/blob/master/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java

    The differences between these two:

    In summary, while double-checked locking is more complicated, it offers significant performance benefits in multi-threaded environments, making it preferable in scenarios where performance is a critical concern.