Card 07/ 09
volatile vs synchronized vs Atomic Classes
Two problems, three tools, and a rule based on how many variables must change together.
Java has three everyday tools for shared state: volatile, synchronized, and the atomic classes such as AtomicInteger. All three make writes visible to other threads; they differ in what they make atomic and in what they cost. Picking by name recognition is how a volatile counter reaches production still losing updates.
| Tool | Makes writes visible | Makes an operation atomic | Costs |
|---|---|---|---|
volatile | Yes | No | Almost nothing |
synchronized | Yes | Yes, for the whole block | A lock; other threads wait |
AtomicInteger and friends | Yes | Yes, for one variable | Very little; no waiting |
volatile boolean stopped; // a flag one thread writes and others read
synchronized void transfer(long pence) { } // several fields changed together
AtomicLong total = new AtomicLong(); // one value, incremented from many threads
total.incrementAndGet();The decision rule. One field that is only ever read and written whole: volatile. One value that is read, computed from and written back: an atomic class. Two or more fields that have to change together: synchronized, because nothing else covers more than one variable.
The atomic classes, such as AtomicLong, work with a compare-and-set loop: read the value, compute the new one, and swap it in only if nothing changed in between, trying again if something did. No thread ever waits, which is why they beat a lock for a single counter, and why they cannot replace one for the money transfer.
← → move through sections and cards