BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ Concurrency

Concurrency

volatile and atomic classes

Atomic classes update a single value as one indivisible step without a lock.

Learn these first

At a glance

Mental model

A counter on a turnstile that always clicks exactly once per person, versus a whiteboard everyone can see but where two people can erase and write at the same time.

What happens, in order
  1. 1count++ is three steps (read, add, write)Two threads can read the same value and both write back value+1, losing one increment. AtomicInteger.incrementAndGet() does it as one step.
  2. 2volatile boolean running guarantees that when one thread sets it to false, others see the change and do not use a stale cached copyIt is right for flags and wrong for read-modify-write.
  3. 3compareAndSet(expected, new) updates only if the current value is what you expect, which is the base for lock-free algorithms
Remember
Watch out
Using volatile for countersAssuming two atomic updates together are atomicCheck-then-act on a plain field
Example (highlighted lines explain it)
private final AtomicInteger hits = new AtomicInteger();private volatile boolean running = true;public void record() { hits.incrementAndGet(); }public void stop() { running = false; }
  1. line 1 uses AtomicInteger, the core of volatile and atomic classes
  2. line 4 uses incrementAndGet, the core of volatile and atomic classes
Read the full explanation (about 1 min)

Atomic classes update a single value as one indivisible step without a lock. volatile makes writes to a field visible to other threads, but does not make count++ safe.

A mental model

A counter on a turnstile that always clicks exactly once per person, versus a whiteboard everyone can see but where two people can erase and write at the same time.

How it works

count++ is three steps (read, add, write). Two threads can read the same value and both write back value+1, losing one increment. AtomicInteger.incrementAndGet() does it as one step.

volatile boolean running guarantees that when one thread sets it to false, others see the change and do not use a stale cached copy. It is right for flags and wrong for read-modify-write.

compareAndSet(expected, new) updates only if the current value is what you expect, which is the base for lock-free algorithms.

Going deeper

For high-contention counters (metrics) LongAdder scales better than AtomicLong. Atomics make single operations safe; invariants spanning several variables still need a lock.

Under the hood

They use the CPU's compare-and-swap instruction through VarHandle/Unsafe. A volatile write inserts memory barriers so earlier writes become visible before it and later reads cannot move before it.

Common mistakes

  • Using volatile for counters.
  • Assuming two atomic updates together are atomic.
  • Check-then-act on a plain field.

How Unravel recognises it

When you paste code, Unravel looks for these signs of volatile and atomic classes. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is volatile and atomic classes?

Atomic classes update a single value as one indivisible step without a lock. volatile makes writes to a field visible to other threads, but does not make count++ safe.

What are the most common mistakes with volatile and atomic classes?

Using volatile for counters. Assuming two atomic updates together are atomic. Check-then-act on a plain field.

How can I see volatile and atomic classes in real code?

Paste your own Java into Unravel and it will point out where volatile and atomic classes appears, explain how it works at the detail level you choose, and draw the flow of the code around it.