volatile
and atomic variables often seem similar at first glance, but they serve different purposes and offer different guarantees in Java concurrency.
🧠 Short Answer:
Feature | volatile | Atomic variables (AtomicInteger , etc.) |
---|---|---|
Guarantees | Visibility only | Visibility + Atomicity |
Atomic operations? | ❌ No | ✅ Yes |
Use for increment? | ❌ Not safe | ✅ Safe (e.g., incrementAndGet() ) |
Use case | Flags, simple single-writer variables | Counters, accumulators, CAS-style logic |
Thread-safe updates | ❌ No | ✅ Yes |
📘 volatile
— Visibility Guarantee
Declaring a variable volatile
ensures that:
- All threads always see the latest value.
- Writes go directly to main memory, and reads always come from main memory.
BUT:
❗
volatile
does not make operations atomic — e.g.,++x
is not thread-safe!
Example — ❌ Broken counter with volatile
volatile int count = 0;
public void increment() {
count++; // Not atomic: read-modify-write
}
Multiple threads calling increment()
can lead to lost updates.
🔐 Atomic Variables (e.g., AtomicInteger
)
These are part of java.util.concurrent.atomic
and provide:
- Atomic read-modify-write operations
- Internally use low-level CAS (Compare-And-Swap) operations
- Extremely efficient and lock-free
Example — ✅ Safe counter with AtomicInteger
AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // atomic
}
This is thread-safe and lock-free.
🔍 Why Atomic*
Is Better for Shared Counters
Let’s say 3 threads try to increment a counter:
- With
volatile
, one might read5
, increment to6
, and write6
, even though others have already made it7
or8
. - With
AtomicInteger
, it’ll internally retry using CAS until the increment is successful.
📦 When to Use What?
Use Case | Best Tool |
---|---|
Stop signal or flag | volatile |
Status monitoring (no increments) | volatile |
Shared counter, sequence number | AtomicInteger |
Lock-free algorithms | Atomic* types |
Compound operations (x += y ) | Atomic* or synchronized |
🧠 Summary
volatile
: Great for simple flags and ensuring visibility.Atomic variables
: Best for safe concurrent updates to counters or shared data.- If you need atomicity, use
Atomic*
orsynchronized
.