Introduction to Concurrency

Your processor has multiple cores. Your operating system runs hundreds of threads. Your users expect responsive interfaces while your server handles thousands of simultaneous connections. Concurrency is not an advanced topic reserved for specialists—​it is the reality of modern software.

Yet concurrent programming has a reputation for being treacherous, and that reputation is earned. Two threads reading and writing the same variable can produce results that are impossible to reproduce and impossible to debug. Such results are also impossible to reason about by staring at the code. A program that passes every test can still corrupt data in production under load. The bugs are real, and they are subtle.

The good news: these problems are well understood. Decades of research and practice have produced clear patterns, precise vocabulary, and reliable tools. Once you understand the fundamentals, concurrent code becomes something you can reason about with confidence. Those fundamentals are what a data race actually is, why memory ordering matters, and how synchronization primitives work.

What This Section Covers

  • Concurrency Foundations — Threads, their lifecycle, and how to create, join, and detach them.

  • Synchronization — Race conditions, mutexes, lock guards, and how to avoid deadlock.

  • Advanced Primitives — Atomics, condition variables, and shared locks for finer-grained synchronization.

  • Communication & Patterns — Futures, promises, std::async, and practical patterns for concurrent code.

When you finish, you have the vocabulary and mental models to understand how Capy’s coroutine-based concurrency works under the hood.