Concurrency
Thread Safety
A class is thread-safe when it behaves correctly under concurrent access with no extra coordination by callers. The core discipline (JCiP): identify shared mutable state, and guard every access to it with the same lock — or remove the sharing, or the mutability.
- The problem is exactly shared + mutable state — remove either property and safety is free
- Race conditions: check-then-act and read-modify-write compound actions are not atomic
- Every shared mutable variable needs one guarding policy, applied on every access — reads too
- Stateless objects and immutable objects are always thread-safe
- Document the policy (
@GuardedBy("lock")thinking) — safety is a design property, not a code style
public class UnsafeCounter {
private long count = 0;
public void increment() { count++; } // read-modify-write: THREE operations
}
// Two threads calling increment() 10,000 times each
// routinely produce a total under 20,000 — lost updates.count++ is load, add, store. Two threads interleave: both load 9, both store 10 — one increment vanishes. Check-then-act is the same disease: if (!map.containsKey(k)) map.put(k, v) can both pass the check. Compound actions must execute atomically relative to other accesses of the same state.
// 1. Synchronize every access (one lock, all accesses):
private long count;
public synchronized void increment() { count++; }
public synchronized long get() { return count; }
// 2. Delegate to an atomic ([[atomics-nonblocking]]):
private final AtomicLong count = new AtomicLong();
public void increment() { count.incrementAndGet(); }
// 3. Don't share: confine to one thread, or make the state immutable.JCiP's design hierarchy: don't share (thread confinement — locals, ThreadLocal, per-request objects), don't mutate (immutable objects), or synchronize consistently. Guarding some accesses is worthless — a single unsynchronized read can observe garbage (Java Memory Model). And atomicity must cover the whole invariant: two AtomicLongs that must change together are not atomic together.