Yes, on x86 there are several possible options.
XADD r/m, r
This command atomically adds the second operand (r) to the first operand (r / m) and loads the second operand (r) with the original value of the first operand (r / m).
To use it, you will need to load the second operand with the increment volume (I guess 1, here), and the first operand should be the memory location of what will be incremented.
This instruction must precede the LOCK prefix (it will make it atomic).
The InterlockedAdd() function in Microsoft Visual C ++ does this, and AFAIR uses XADD if available (available since i80486).
Another way is to use a loop with the CMPXCHG ...
pseudo code:
while (true) { int oldValue = ln; int newValue = oldValue + 1; if (CAS(&l.n, newValue, oldValue) == oldValue) break; }
CAS() , which stands for Compare And Swap (a generic term in parallel programming), is a function that attempts to atomically replace a value in memory with a new value. Replacement succeeds when the value being replaced is equal to the last parameter, oldValue . This is not true. CAS returns the original value from memory, which allows us to find out if the replacement was successful (we compare the return value with oldValue ). An error (the return value is different from oldValue ) means that between reading oldValue and the moment we tried to replace it with newValue , another thread changed the value in memory. In this case, we simply repeat the whole procedure.
The CMPXCHG instruction is an x86 CAS .
Microsoft Visual C ++ InterlockedCompareExchange() uses CMPXCHG to implement CAS .
If XADD not available, InterlockedAdd() is implemented using CAS / CMPXCHG / InterlockedCompareExchange() .
Some other CPUs may have different capabilities. Some of them allow atomic execution of several related instructions.