Singleton

One instance, globally reachable — and why that's more controversial than it looks.

Exactly one instance, reachable from anywhere. It's the pattern everyone learns first and the one most likely to be a trap in an interview, because the question is rarely "can you write it" and usually "do you know why people regret it".

Mechanically the interesting part is laziness plus threads. A naive lazy getter can let two threads both see a null instance and both construct one. Synchronising the whole method fixes it and costs a lock on every read; double-checked locking narrows that but is only correct if the field prevents the reordering that can publish a half-constructed object — volatile in Java, and it was genuinely broken in older memory models. The boring fixes are usually better: initialise eagerly, or in Java use an enum or a static holder class and let class loading do the locking for you.

The real objection is design, not concurrency. A singleton is global mutable state wearing a nicer hat, so anything that touches it is hard to test in isolation and its dependencies stop appearing in constructor signatures — you can no longer tell what a class needs by looking at it. "One instance" and "reachable from anywhere" are separable, and dependency injection gives you the first without the second. Say that, and you've answered the question the interviewer was actually asking.

What they ask, and what to say

What breaks in a naive lazy singleton under concurrency?

Two threads can both find the instance null and both construct one, so "exactly one" quietly stops being true. Synchronising the accessor fixes it at the cost of a lock per read; double-checked locking needs the field to be volatile or a caller can see a partly constructed object.

Why they ask: The most common concurrency question attached to a pattern, and the volatile detail is what separates memorised from understood.

Why do people argue against Singleton?

It's global mutable state. It hides dependencies — they no longer show up in a constructor — and makes isolated testing hard because you can't substitute it. Note the two properties are separable: dependency injection gives you one shared instance without global reachability.

Why they ask: The whole reason it gets asked. Someone who only recites the implementation walks into this.

You need exactly one database connection pool. Singleton?

One instance, yes — a global access point, not necessarily. Construct it once at startup and inject it into whoever needs it. You keep the single instance and the callers still declare what they depend on.

Why they ask: Turns an abstract objection into a concrete alternative, which is what a senior answer sounds like.