Skip to content

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 threadsPrivate to each thread
The heapThe stack
Global variablesRegisters
Open file descriptorsProgram counter
The code itselfIts 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

c
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:

code
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 result

This is a race condition, and the region of code where it happens is the critical section.