Skip to content

Latest commit

 

History

History
160 lines (110 loc) · 3.78 KB

File metadata and controls

160 lines (110 loc) · 3.78 KB

Q16 — Singleton Pattern Implementation

Interview Tip: Show all 3 versions — basic (broken), synchronized (slow), double-checked locking (production). Then mention enum singleton.


🔑 What is Singleton?

Ensures a class has only one instance throughout the application.

Constructor is private — so no one can do new MyClass() from outside.


💻 Version 1 — Basic (Not Thread-Safe ❌)

public class Singleton {

    private static Singleton instance;

    private Singleton() {   // private constructor — key!
        System.out.println("Singleton created");
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();  // ❌ Two threads can enter here simultaneously
        }
        return instance;
    }
}

Problem: Two threads can both see instance == null and both create instances → breaks singleton.


💻 Version 2 — Synchronized (Thread-Safe but Slow ⚠️)

public class Singleton {

    private static Singleton instance;

    private Singleton() {}

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

Problem: synchronized on every call — performance hit even after instance is created.


💻 Version 3 — Double-Checked Locking ✅ (Production Standard)

public class Singleton {

    private static volatile Singleton instance;   // volatile is critical!

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {                    // first check — no sync needed
            synchronized (Singleton.class) {
                if (instance == null) {            // second check — inside sync
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Why volatile? Without it, CPU instruction reordering can cause a partially constructed object to be seen by another thread.


💻 Version 4 — Enum Singleton ✅ (Joshua Bloch Recommended)

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("Doing work in singleton");
    }
}

// Usage
Singleton.INSTANCE.doSomething();

Benefits:

  • Thread-safe by default
  • Prevents reflection attacks (can't instantiate enum via reflection)
  • Handles serialization automatically

💻 Version 5 — Bill Pugh (Static Inner Class) ✅ Clean

public class Singleton {

    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;  // loaded only when first accessed
    }
}

Why it works: Inner class is loaded lazily by JVM — only when getInstance() is called. JVM class loading is thread-safe.


📌 Constructor — Why Private?

  • private constructor → prevents new Singleton() from anywhere else
  • No public or protected constructor
  • Subclassing is also prevented (can't extend a class with private constructor)

📌 Advantages & Disadvantages

Advantages Disadvantages
Single shared instance Hard to unit test (global state)
Saves memory Tight coupling
Consistent state Multi-threading needs care
Lazy or eager init Violates Single Responsibility in some designs

📌 Spring Boot Context

In Spring Boot, all beans are Singleton by default (per ApplicationContext).

@Service  // → singleton by default
public class UserService { }

@Service
@Scope("prototype")  // → new instance each time
public class ReportService { }