Concurrency Demystified
Processes, threads, sync, async & coroutines — visualized
Concurrency, Parallelism & Asynchrony
Modern programs rarely do just one thing. They fetch data, process files, handle user input, and talk to databases — often at the same time. But "at the same time" can mean very different things depending on how your program is structured.
Here's the core question: when two tasks need to run, are they truly simultaneous, or just taking turns very quickly?
The answer shapes everything — performance, memory usage, bugs, and which tools you reach for.
Five Concepts You Need to Know
Processes
Isolated memory spaces. True parallelism on multiple CPU cores. Heavy but safe.
Threads
Lightweight workers sharing memory. Good for I/O. Limited by Python's GIL for CPU work.
Synchronous
Tasks run one after another. Simple to reason about. Blocks while waiting.
Asynchronous
Tasks yield while waiting for I/O. Single thread, cooperative scheduling.
Coroutines
Functions that can pause and resume. The building block of async/await.
A Quick Mental Model
Sync — a single chef who finishes one dish completely before starting the next.
Async — a single chef who puts dish A in the oven, works on dish B while waiting, then comes back.
Threads — multiple chefs sharing one kitchen (and one knife — the GIL).
Processes — multiple chefs in separate kitchens. Fully independent.
Coroutines — one chef who explicitly decides when to pause and hand off control.