In C, is i+=1;
atomic?
No, i += 1 is not guaranteed to atomic. Changing memory values is never atomic. It implies reading from memory, incrementing the value and writing the result back to memory.
No, it isn't. If the value of i is not loaded to one of the registers already, it cannot be done in one single assembly instruction.
Not usually.
If i
is volatile
, then it would depend on your CPU architecure and compiler - if adding two integers in main memory is atomic on your CPU, then that C statement might be atomic with a volatile int i
.
It really depends on your target and the mnemonic set of your uC/processor. If i is a variable held in a register then it is possible to have it atomic.
The C standard does not define whether it is atomic or not.
In practice, you never write code which fails if a given operation is atomic, but you might well write code which fails if it isn't. So assume it isn't.
No.
The only operation guaranteed by the C language standard to be atomic is assigning or retrieving a value to/from a variable of type sig_atomic_t
, defined in <signal.h>
.
(C99, chapter 7.14 Signal handling.)
The C / C++ language itself makes no claim of atomicity or lack thereof. You need to rely on intrinsics or library functions to ensure atomic behavior.
Just put a mutex or a semaphore around it. Of course it is not atomic and you can make a test program with 50 or so threads accessing the same variable and incrementing it, to check it for yourself
Whether the expression is atomic or not depends only on the machine code that the compiler generates, and the CPU architectre that it will run on. Unless the addition can be achieved in one machine instruction, its unlikely to be atomic.
If you are using Windows then you can use the InterlockedIncrement() API function to do a guaranteed atomic increment. There are similar functions for decrement, etc.
Although i may not be atomic for the C language, it should be noted that is atomic on most platforms. The GNU C Library documentation states:
In practice, you can assume that int and other integer types no longer than int are atomic. You can also assume that pointer types are atomic; that is very convenient. Both of these assumptions are true on all of the machines that the GNU C library supports and on all POSIX systems we know of.
No, the C standard doesn't guarantee atomicity, and in practice, the operation won't be atomic. You have to use a library (eg the Windows API) or compiler builtin functions (GCC, MSVC).
Defined in C, no. In practice, maybe. Write it in assembly.
The standard make no guarantees.
Therefore a portable program would not make the assumption. It's not clear if you mean "required to be atomic", or "happens to be atomic in my C code", and the answer to that second question is that it depends on a lot of things:
Not all machines even have an increment memory op. Some need to load and store the value in order to operate on it, so the answer there is "never".
On machines that do have an increment memory op, there is no assurance that the compiler will not output a load, increment, and store sequence anyway, or use some other non-atomic instruction.
On machines that do have an increment memory operation, it may or may not be atomic with respect to other CPU units.
On machines that do have an atomic increment memory op, it may not be specified as part of the architecture, but just a property of a particular edition of the CPU chip, or even just of certain core logic or motherboard designs.
As to "how do I do this atomically", there is generally a way to do this quickly rather than resort to (more expensive) negotiated mutual exclusion. Sometimes this involves special collision-detecting repeatable code sequences. It's best to implement these in an assembly language module, because it's target-specific anyway so there is no portability benefit to the HLL.
Finally, because atomic operations that do not require (expensive) negotiated mutual exclusion are fast and hence useful, and in any case needed for portable code, systems typically have a library, generally written in assembly, that already implements similar functions.
The answer to your question depends on whether i
is a local, static
, or global variable. If i
is a static
or global variable, then no, the statement i += 1
is not atomic. If, however, i
is a local variable, then the statement is atomic for modern operating systems running on the x86 architecture and probably other architectures as well. @Dan Cristoloveanu was on the right track for the local variable case, but there is also more that can be said.
(In what follows, I assume a modern operating system with protection on an x86 architecture with threading entirely implemented with task switching.)
Given that this is C code, the syntax i += 1
implies that i
is some kind of integer variable, the value of which, if it is a local variable, is stored in either a register such as %eax
or in the stack. Handling the easy case first, if the value of i
is stored in a register, say %eax
, then the C compiler will most likely translate the statement to something like:
addl $1, %eax
which of course is atomic because no other process/thread should be able to modify the running thread's %eax
register, and the thread itself cannot modify %eax
again until this instruction completes.
If the value of i
is stored in the stack, then this means that there is a memory fetch, increment, and commit. Something like:
movl -16(%esp), %eax
addl $1, %eax
movl %eax, -16(%esp) # this is the commit. It may actually come later if `i += 1` is part of a series of calculations involving `i`.
Normally this series of operations is not atomic. However, on a modern operating system, processes/threads should not be able to modify another thread's stack, so these operations do complete without other processes being able to interfere. Thus, the statement i += 1
is atomic in this case as well.