Command Palette

Search for a command to run...

PHASE 2Beginner ~7 min· topic 5 of 22Creational

Creational 5 — Singleton

In one line

One instance per JVM, with a globally reachable accessor. Interviews love it because naive implementations break under concurrency.

0/22 · 0%

Think of it like this

A country's president. There is only one at a time, and everyone who asks 'who is the president?' gets the same person.

Key ideas

  1. 01

    The 4 safe forms: eager static final, enum, holder (Bill Pugh), and double-checked locking.

  2. 02

    Why singletons are criticized: hidden global state, hard to test, hard to replace.

  3. 03

    In Spring, singletons are the framework's job (one bean per context) — you usually don't write one.

  4. 04

    Double-checked locking needs volatile to publish the instance safely.

  5. 05

    The enum form also resists reflection and serialization attacks, which can create a second instance of the other forms.

Java / Spring map

  • →

    Spring @Singleton-scoped beans; java.lang.Runtime, System are de-facto singletons.

Code & diagrams

SafeSingletons.javajava

All four concurrency-safe forms.

// 0) Eager — simplest; built when the class is initialized
public final class ConfigEager {
  private static final ConfigEager INSTANCE = new ConfigEager();
  private ConfigEager() {}
  public static ConfigEager get() { return INSTANCE; }
}

// 1) Enum — best, serialization- and reflection-safe, thread-safe by construction
public enum ConfigEnum { INSTANCE;
  private final int maxRetries = 3;
  public int maxRetries() { return maxRetries; }
}

// 2) Holder (Bill Pugh) — lazy, no synchronized on the hot path
public final class ConfigHolder {
  private ConfigHolder() {}
  private static final class Holder { static final ConfigHolder I = new ConfigHolder(); }
  public static ConfigHolder get() { return Holder.I; }
}

// 3) Double-checked locking
public final class ConfigDCL {
  private static volatile ConfigDCL INSTANCE;         // volatile is the key
  private ConfigDCL() {}
  public static ConfigDCL get() {
    if (INSTANCE == null) {                            // fast path, no lock
      synchronized (ConfigDCL.class) {
        if (INSTANCE == null) INSTANCE = new ConfigDCL();
      }
    }
    return INSTANCE;
  }
}

Explain without notes

01

Why is double-checked locking safe only with volatile?

Practice

01

Write a thread-safe singleton you could use in a multi-threaded rate limiter (you'll need it in Phase 5).

Trade-offs

  • ↔

    Singleton hides global mutable state — Spring DI is the testable alternative.

Completion checklist

  • I can write all four safe forms and explain why naive lazy init breaks under concurrency.

Back to phase