Unravel โบ Java concepts โบ Design patterns and architecture
Singleton pattern
A singleton guarantees one shared instance of a class: a private constructor plus a static accessor.
Learn these first
At a glance
The mayor of a town: there is exactly one, everybody asks the same person, and nobody else can hold the office.
- 1The simplest safe forms: an enum (enum Config { INSTANCE; ..}), an eager static field (private static final Config INSTANCE = new Config();), or a holder class that loads lazily (private static class Holder { static final Config I = new Config(); }).
- 2Lazy creation with if (instance == null) instance = new X(); is not thread safe: two threads may create two instancesFix with double-checked locking and a volatile field, or use the holder idiom.
- 3The private constructor stops new, but reflection, serialization (readResolve) and multiple class loaders can still create copies, which an enum prevents
- 4In Spring every bean is a singleton per container by default, managed for you, which is the better form: the object is created once and passed in where needed
- Singletons are global state in disguise: hidden dependencies, hard to replace in a test, and trouble when you later need two of them (two tenants, two databases)
- A singleton that holds mutable state needs its own thread safety, or it becomes a shared race condition for the whole program
- The holder idiom works because the JVM initialises a class lazily and exactly once under a lock, so the inner class is loaded on first use of getInstance() without any explicit synchronisation
public class Registry { private static volatile Registry instance; private final java.util.Map<String, String> entries = new java.util.concurrent.ConcurrentHashMap<>(); private Registry() {} public static Registry getInstance() { if (instance == null) { synchronized (Registry.class) { if (instance == null) instance = new Registry(); } } return instance; } public void register(String k, String v) { entries.put(k, v); }}Read the full explanation (about 1 min)
A singleton guarantees one shared instance of a class: a private constructor plus a static accessor. It is easy to write, easy to get wrong with threads, and hard to test; dependency injection usually replaces it.
A mental model
The mayor of a town: there is exactly one, everybody asks the same person, and nobody else can hold the office.
How it works
The simplest safe forms: an enum (enum Config { INSTANCE; ... }), an eager static field (private static final Config INSTANCE = new Config();), or a holder class that loads lazily (private static class Holder { static final Config I = new Config(); }).
Lazy creation with if (instance == null) instance = new X(); is not thread safe: two threads may create two instances. Fix with double-checked locking and a volatile field, or use the holder idiom.
The private constructor stops new, but reflection, serialization (readResolve) and multiple class loaders can still create copies, which an enum prevents.
In Spring every bean is a singleton per container by default, managed for you, which is the better form: the object is created once and passed in where needed.
Going deeper
Singletons are global state in disguise: hidden dependencies, hard to replace in a test, and trouble when you later need two of them (two tenants, two databases). Prefer passing dependencies explicitly.
A singleton that holds mutable state needs its own thread safety, or it becomes a shared race condition for the whole program.
Under the hood
The holder idiom works because the JVM initialises a class lazily and exactly once under a lock, so the inner class is loaded on first use of getInstance() without any explicit synchronisation.
Common mistakes
- Lazy initialisation without synchronisation.
- Double-checked locking without
volatile. - A mutable singleton used as a global variable.
- Forgetting that each class loader gets its own "singleton".
How Unravel recognises it
When you paste code, Unravel looks for these signs of singleton pattern. Spotting them yourself is a good habit when you read unfamiliar code:
- Method names you declare:
getInstance()
Part of a learning path
- Design patterns and SOLID ยท next: Builder pattern
Related concepts
Frequently asked questions
What is Singleton pattern?
A singleton guarantees one shared instance of a class: a private constructor plus a static accessor. It is easy to write, easy to get wrong with threads, and hard to test; dependency injection usually replaces it.
What are the most common mistakes with Singleton pattern?
Lazy initialisation without synchronisation. Double-checked locking without volatile. A mutable singleton used as a global variable. Forgetting that each class loader gets its own "singleton".
How can I see Singleton pattern in real code?
Paste your own Java into Unravel and it will point out where singleton pattern appears, explain how it works at the detail level you choose, and draw the flow of the code around it.