Thread-Safety Patterns — Java Interview Guide | Cracked Java
Senior

Thread-Safety Patterns

Designing for concurrency: what thread-safe really means, immutability, confinement, ThreadLocal and its leak risk, safe publication, and the holder idiom for lazy initialization.

Prereqs: jmm-happens-before

Thread-safety is a property of a class, not a feature you bolt on: a class is thread-safe if it behaves correctly when accessed from multiple threads with no external synchronization, regardless of how those threads are scheduled. The patterns in this topic are the toolkit for getting there — and most of them avoid locks entirely. The cheapest concurrent code is code that shares nothing mutable.

The strategies, cheapest first

There is a rough hierarchy of how you make state safe to share. Don't share it — confine mutable state to a single thread (thread or stack confinement). Make it immutable — if state never changes after construction, no thread can observe it in a half-built form, so it needs no synchronization at all. Publish it safely — when you must share an object, ensure other threads see a fully-constructed version, using final fields, volatile, static initializers, or concurrent collections. Only when none of those fit do you reach for locks or atomics.

Confinement and ThreadLocal

Confinement keeps an object reachable from exactly one thread. ThreadLocal<T> formalizes per-thread state — each thread sees its own value — which is why SimpleDateFormat (not thread-safe) is often wrapped in one. The catch: on a pooled thread that lives forever, a ThreadLocal entry is never garbage-collected on its own and can pin large objects or even classloaders. Always remove() in a finally block.

Safe publication and lazy init

The JMM only guarantees other threads see a correctly-built object if it was published safely. Leaking this from a constructor (registering a listener, starting a thread) breaks that — final fields may not yet be frozen. For lazy initialization the initialization-on-demand holder idiom beats double-checked locking: it leans on the JVM's guaranteed-safe class-init lock, giving lazy, lock-free, correct singletons with no volatile and no synchronization in the hot path.

Questions

6 in this topic