C was designed to run on a simple serial computer. But increasing numbers of machines have more than one CPU, and low-level code (the kind still written in C) has to work around this issue.
The current specification defines a sig_atomic_t type, which is guaranteed to be atomic with respect to a single CPU. If you begin an operation on this type, that operation cannot be interrupted—but that guarantee applies only to the current thread. If two threads are running on separate CPUs, modifications to a sig_atomic_t value are not guaranteed to be atomic with respect to each other.
All modern CPUs that support multiprocessor configurations provide instructions that allow multiple threads. On RISC architectures, this is typically implemented as a conditional load and store: You load a value, modify it, and then attempt to write it back. If the memory at the specified location has changed, the store fails and a condition bit is set. Then you can jump back to the load instruction and try again.
More CISC-y chips, such as x86, provide higher-level constructs, such as atomic add instructions. These aren’t exposed to C at all. If you want to perform SMP-safe atomic operations, you typically have to resort to inline assembler, which defeats the point of using C in the first place. I would like to see C0x define an atomic qualifier. Operations on variables declared as atomic are guaranteed to be SMP-safe and thread-safe. Suppose you do this:
extern atomic int i = 1; ... i++;
The increment will never be lost, no matter how many other threads or processes are manipulating i at the same time. Of course, this imposes a performance penalty, but C has always been about allowing programmers to do something that’s deeply wrong, and assuming that they’re intelligent enough not to try it.