Card 02/ 09
Atomic Operations: Why count++ Is Three Steps
Read, add and write, and another thread can get in between any two of them.
An operation is atomic when no other thread can see it half done or run in the middle of it. count++ looks like one thing happening, and it is not atomic: it is three separate steps, and the gaps between them are where an update goes missing.
| Step | What happens |
|---|---|
| Read | Fetch the current value of count |
| Add | Work out that value plus one |
| Write | Store the result back into count |
Another thread can run between any two of those steps. If both threads read 41 before either writes, both work out 42, and both write 42: two increments, and the count went up by one.
count++ is not the only one. balance = balance - amount is not atomic, nor is if (map.get(k) == null) map.put(k, v), nor anything else that reads a value, computes from it, and writes it back.
So the question to ask of any line that touches shared state is how many steps it really is. Reading a field is one step and writing one is one step; everything between them is a gap another thread can get into. A plain long or double is the rare exception even there: Java allows a single write to one to be split into two 32-bit halves, unless the field is volatile, a modifier that makes reads and writes of it whole and visible to every thread.
← → move through sections and cards