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

🏭multiprocessing

Processes

Isolated memory spaces. True parallelism on multiple CPU cores. Heavy but safe.

🧵threading

Threads

Lightweight workers sharing memory. Good for I/O. Limited by Python's GIL for CPU work.

blocking

Synchronous

Tasks run one after another. Simple to reason about. Blocks while waiting.

asyncio

Asynchronous

Tasks yield while waiting for I/O. Single thread, cooperative scheduling.

🔄yield / await

Coroutines

Functions that can pause and resume. The building block of async/await.

A Quick Mental Model

01

Sync — a single chef who finishes one dish completely before starting the next.

02

Async — a single chef who puts dish A in the oven, works on dish B while waiting, then comes back.

03

Threads — multiple chefs sharing one kitchen (and one knife — the GIL).

04

Processes — multiple chefs in separate kitchens. Fully independent.

05

Coroutines — one chef who explicitly decides when to pause and hand off control.