Chaturmind
LearnDSASystem DesignBlogPremium
Sign inGet started
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML

Company

  • Blog
  • Premium
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight
HomeLearnSystem DesignLow-Level Design & Design PatternsCreational Design Patterns
✓ FreeIntermediate· 7 min read

Singleton Pattern

Why Singleton is the most-used and most-misused pattern in interviews: double-checked locking and why volatile matters, the enum alternative, and when it's an anti-pattern.

Published September 22, 2026


Singleton Pattern

Singleton guarantees a class has exactly one instance and gives it a global access point. It's the first pattern most people learn — and the one most people implement incorrectly under interview pressure.

The naive version (and why it fails)

public class ConfigManager {
    private static ConfigManager instance;
    private ConfigManager() {}

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

This is not thread-safe. Two threads can both pass the null check before either assigns instance, producing two separate instances — silently, with no exception, only visible under load.

The double-checked locking fix — and why volatile is not decoration

public class ConfigManager {
    private static volatile ConfigManager instance;
    private ConfigManager() {}

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

Checking instance == null twice (once outside the lock, once inside) avoids paying the synchronization cost on every call — only the first, racing calls ever enter the lock.

The volatile keyword is the detail that separates a correct answer from a memorized one. Without it, another thread can observe a partially constructed ConfigManager — the JVM is allowed to reorder the constructor's writes and the reference assignment, so a reader could see a non-null reference to an object whose fields aren't fully initialized yet. volatile inserts the memory barrier (a happens-before edge) that prevents that reordering, guaranteeing any thread that sees a non-null instance also sees a fully constructed one.

Enum singleton — the simplest thread-safe alternative

public enum ConfigManager {
    INSTANCE;
    public void loadConfig() { /* ... */ }
}

The JVM guarantees a class is initialized lazily and thread-safely on first access, and guarantees exactly one instance per enum constant — at the language level, not through code you have to get right yourself. It's also immune to two attacks double-checked locking isn't: reflection can call a private constructor directly (Constructor.setAccessible(true)), and naive serialization can deserialize a second instance — neither works against an enum singleton, because the JVM enforces single-instance-per-constant as a language guarantee, not an implementation detail.

When Singleton is the right call — and when it's an anti-pattern

Reasonable uses: truly global, stateless (or read-mostly) resources — a configuration loader, a connection pool manager, a logging facade.

Where it becomes an anti-pattern:

  • Hidden dependencies — a class calling ConfigManager.getInstance() internally has an invisible dependency that doesn't show up in its constructor signature, making the coupling hard to see from the outside.
  • Hard to test — you can't substitute a mock or fake in place of a hard-coded getInstance() call the way you could with a constructor-injected dependency (see Dependency Inversion).
  • Global mutable state — in a multi-tenant backend, a naively-written Singleton can leak state across requests/tenants if it isn't carefully scoped.

In most Spring applications, a @Service-annotated bean already gives you a container-managed singleton (one instance per application context) and keeps the class constructor-injectable and testable — which is why hand-rolled Singleton in application code is increasingly rare outside of infrastructure-level utility classes.

Follow-up questions this topic invites — and their answers

Q: Is the enum singleton always better than double-checked locking? A: For most practical purposes, yes — it's shorter, immune to reflection/serialization attacks, and the JVM handles thread safety for you. Double-checked locking is worth knowing because interviewers use it to test whether you understand volatile and the JMM, not because it's the recommended way to write a singleton today.

Q: What's the 'initialization-on-demand holder' pattern, and is it better than double-checked locking? A: A static nested class whose only field is the singleton instance — the JVM's own class-initialization guarantees (lazy, thread-safe) do the synchronization work implicitly, with no explicit lock or volatile needed. It's arguably cleaner than double-checked locking for exactly that reason, though enum singleton remains the most attack-resistant option of the three.

Q: Can Spring's singleton-scoped bean have the same hidden-dependency problem as a hand-rolled Singleton? A: Only if code reaches for it via a static accessor or ApplicationContext.getBean() instead of constructor injection — the container's singleton scope isn't the problem, it's whether the dependency is made explicit through the constructor or hidden behind a global lookup.

Previous

Dependency Inversion

Next

Factory & Abstract Factory

AI Tutor

Lesson: Singleton Pattern

Quick actions

AI responses can be inaccurate. Verify critical information.