8/32 · 5 min
Threads, and the shared memory that bites
A process has one thread of execution by default. Give it two, and they run at the same time inside the same address space.
What is shared, what is not
| Shared between threads | Private to each thread |
|---|---|
| The heap | The stack |
| Global variables | Registers |
| Open file descriptors | Program counter |
| The code itself | Its own local variables |
The shared heap is the entire point. Passing a megabyte between two threads costs a pointer; passing it between two processes costs a copy through a pipe.
It is also the entire danger.
The bite
int counter = 0; // shared
void *increment(void *_) {
for (int i = 0; i < 100000; i++) counter++;
return NULL;
}Two threads, a hundred thousand increments each. The answer is not 200,000. It is some number below it, different every run.
counter++ is three machine instructions: read, add one, write back. Two threads interleave:
Thread A reads counter (0)
Thread B reads counter (0)
Thread A adds one, writes (1)
Thread B adds one, writes (1) <- two increments, one resultThis is a race condition, and the region of code where it happens is the critical section.