Although we normally think of a process as having a single control flow, in modern systems a process can actually consist of multiple execution units, called threads, each running in the context of the process and sharing the same code and global data.
Comprises a thread ID, a program counter, a register set, and a stack.
- Race conditions, where threads are accessing data or resources in an inconsistent order
- Deadlocks, where two threads are waiting for each other, preventing both threads from continuing
- Bugs that happen only in certain situations and are hard to reproduce and fix reliably
Thread-safe code ensures that when a thread is modifying or reading shared data, no other thread can access it in a way that changes the data