Sunday, 30 August 2026

Volatile vs AtomicInteger vs Synchronized

 Absolutely. The key idea is:

volatile gives visibility, but NOT atomicity.

Let's use a simple Java example.

1. volatile boolean running

volatile boolean running = true;

Suppose we have two threads:

Thread 1                    Thread 2
--------                    --------
running = false  -------->  while (running) {
                                // sees false
                            }

Because running is volatile, when Thread 1 changes it, Thread 2 is guaranteed to see the latest value.

So:

running = false;

is effectively safe for a simple read/write flag.


2. But count++ is different

Consider:

volatile int count = 0;

You might think:

count++;

is safe because count is volatile.

It isn't.

Why?

Because:

count++;

is actually three operations:

1. READ count
2. ADD 1
3. WRITE count

Equivalent to:

int temp = count;  // READ
temp = temp + 1;   // MODIFY
count = temp;      // WRITE

3. Two threads cause the problem

Suppose:

volatile int count = 0;

Two threads both execute:

count++;

You might expect:

Thread 1: count++
Thread 2: count++

Final count = 2

But this can happen:

Initial count = 0

Thread 1                    Thread 2
--------                    --------
READ count → 0
                            READ count → 0

ADD 1 → 1
                            ADD 1 → 1

WRITE count → 1
                            WRITE count → 1

Final count = 1 ❌

Both threads saw the latest value at the time they read it, but they both read the same value 0.

The second write overwrites the first write.

This is called a lost update.


4. So what exactly does volatile guarantee?

Think of volatile as:

              volatile
                 │
        ┌────────┴────────┐
        ↓                 ↓
   Visibility         Ordering
        │
        ↓
Other threads can
see the latest write

But it does NOT turn a multi-step operation into one indivisible operation.

volatile count

READ ──→ MODIFY ──→ WRITE
  ↑                    ↑
  └──── other thread can interfere

5. Compare these two

volatile boolean

volatile boolean running = true;

running = false;

This is a single read/write operation.

Good use of volatile.

volatile counter

volatile int count = 0;

count++;

This is:

READ → MODIFY → WRITE

Not atomic.


6. How to make count++ thread-safe?

Use AtomicInteger:

AtomicInteger count = new AtomicInteger(0);

count.incrementAndGet();

Now the increment is atomic:

Thread 1 ── increment ──┐
                         ├──> Atomic operation
Thread 2 ── increment ──┘

Or use synchronization:

synchronized void increment() {
    count++;
}

Easy way to remember

FeaturevolatileAtomicIntegersynchronized
Latest value visible
count++ atomic
Prevents lost updates
Good for simple flag

One-line memory trick ๐Ÿง 

volatile = "Everyone sees my latest value."

atomic = "Nobody can interrupt my operation halfway."

So:

volatile boolean running;

✅ Good for a stop/start flag

while:

volatile int count;
count++;

❌ Not enough for a shared counter.

No comments:

Post a Comment