Does one assembler instruction always execute atomically?

assembly, atomic, multithreading, race-condition

Solution

Specifically for x86, and regarding your example: `counter++`, there are a number of ways it could be compiled. The most trivial example is:

inc counter

This translates into the following micro operations:

- load `counter` to a hidden register on the CPU

- increment the register

- store the updated register in `counter`

This is essentially the same as:

mov eax, counter
inc eax
mov counter, eax

Note that if some other agent updates `counter` between the load and the store, it won't be reflected in `counter` after the store. This agent could be another thread in the same core, another core in the same CPU, another CPU in the same system, or even some external agent that uses DMA (Direct Memory Access).

If you want to guarantee that this `inc` is atomic, use the `lock` prefix:

lock inc counter

`lock` guarantees that nobody can update `counter` between the load and the store.

Regarding more complicated instructions, you usually can't assume that they'll execute atomically, unless they support the `lock` prefix.

Problem

Today I came across this question: you have a code ``` static int counter = 0; void worker() { for (int i = 1; i <= 10; i++) counter++; } ``` If `worker` would be called from two different threads, what value will `counter` have after both of them are finished? I know that actually it could be anything. But my internal guts tells me, that `counter++` will most likely be translated into single assembler instruction, and if both threads are execute on the same core, `counter` will be 20. But what if those threads are run on different cores or processors, could there be a race condition in their microcode? Is one assembler instruction could always be viewed as atomic operation?

Original source

Related problems