synchronized | volatile | |
|---|---|---|
| Mutual exclusion | ✅ 1 thread vào block | ❌ |
| Atomicity (compound op) | ✅ | ❌ |
| Visibility (memory) | ✅ | ✅ |
| Cost | Đắt (lock contention, context switch) | Rẻ (memory barrier) |
synchronized dùng cho: critical section đa bước, compound op (count++, check-then-act).
volatile dùng cho: boolean flag, reference immutable object, singleton DCL.
// synchronized
synchronized (lock) { count++; } // atomic + visible
// volatile — chỉ visible, KHÔNG atomic
volatile boolean stop = false; // OK cho flag
volatile int count;
count++; // ❌ vẫn raceHiện đại: cần atomicity → dùng AtomicInteger/AtomicReference (CAS, rẻ hơn synchronized). Cần lock có timeout/fairness → ReentrantLock.
volatile không phải "synchronized rẻ" — chỉ giải quyết visibility, không phải mutex.
synchronized | volatile | |
|---|---|---|
| Mutual exclusion | ✅ one thread per block | ❌ |
| Atomicity (compound op) | ✅ | ❌ |
| Visibility (memory) | ✅ | ✅ |
| Cost | Expensive (lock contention, context switch) | Cheap (memory barrier) |
synchronized for: multi-step critical sections, compound ops (count++, check-then-act).
volatile for: boolean flags, immutable object references, singleton DCL.
// synchronized
synchronized (lock) { count++; } // atomic + visible
// volatile — visible only, NOT atomic
volatile boolean stop = false; // OK for flags
volatile int count;
count++; // ❌ still racesModern: for atomicity → use AtomicInteger/AtomicReference (CAS, cheaper than synchronized). For locks with timeout/fairness → ReentrantLock.
volatile is not "cheap synchronized" — it only solves visibility, not mutual exclusion.