Concurrency is the ability to execute multiple tasks in overlapping time periods, while parallelism executes multiple tasks simultaneously on multiple cores or processors. These concepts are fundamental to building performant, responsive software systems that leverage modern multi-core hardware. The key challenge lies not in spawning threads or processes, but in coordinating their access to shared resources without introducing subtle, hard-to-reproduce bugs. Understanding the distinction between concurrency models (threads, processes, coroutines), synchronization primitives (mutexes, semaphores, barriers), and common pitfalls (race conditions, deadlocks, false sharing) transforms concurrent programming from an intimidating minefield into a structured engineering discipline with predictable trade-offs and proven patterns.
What This Cheat Sheet Covers
This topic spans 11 focused tables and 80 indexed concepts. Below is a complete table-by-table outline of this topic, spanning foundational concepts through advanced details.
Table 1: Concurrency Models
| Model | Example | Description |
|---|---|---|
std::thread t(func);t.join(); | • OS-managed execution unit sharing process memory space • preemptively scheduled by kernel • ~1MB stack overhead per thread • suitable for CPU-bound parallel work. | |
fork() in Unixmultiprocessing.Process() in Python | • Independent execution unit with separate memory space • isolated from other processes • higher creation/context-switch cost • communicates via IPC • avoids shared-memory race conditions. | |
async def fetch(): await http.get(url) | • Cooperatively-scheduled function that can suspend and resume execution • lightweight (~KB overhead) • ideal for I/O-bound tasks • requires explicit yield points • avoids preemption overhead. | |
go func() { ... }() | • Go's lightweight threads managed by Go runtime • multiplexed onto OS threads (M:N model) • starts with 2KB stack that grows dynamically • extremely cheap to spawn thousands. |