Visual course · Systems fundamentals

How concurrency works.

Concurrency is where confident engineers get humbled — the bugs are rare, non-deterministic, and brutal to reproduce. This course builds the whole mental model from the ground up: why shared state races, how locks fix it and what they break, how deadlock and the event loop actually work, and how the actor model sidesteps the problem entirely. Seven short episodes, each embedded with the deeper reference.

7 episodes ~90 min Visual / first-principles Free · no sign-up
Your progress0 / 7 complete

What you'll understand

By the end you'll be able to reason about concurrent code instead of fearing it: spot the race in a read-modify-write, know when a mutex helps and when it deadlocks, tell threads from processes and know which to reach for, explain how a single-threaded event loop serves thousands of connections, draw the line between concurrency and parallelism, and know why message-passing designs dodge whole categories of bug. It's the systems-interview core and the daily reality of any real backend.

Race conditionsMutexesCritical sectionsDeadlockThreadsProcessesAsyncEvent loopParallelismActors
The curriculum

Seven episodes, in order

01
Episode 1 · Race Conditions

The Bug That Changes Every Time You Run It

When two threads touch the same data at once, the result depends on who wins the race — and the answer changes run to run. This lost-update bug is the root of most concurrency pain; once you can see it happen step by step, everything else in the course is a response to it.

What you'll learn
  • Read-modify-write and the lost update
  • Why the bug is non-deterministic
  • What "shared mutable state" really costs
02
Episode 2 · Locks & Mutexes

One Thread at a Time, Please

A mutex is a turnstile: only one thread holds it at a time, so the critical section runs alone and the race is gone. Locks are the first real tool against shared-state bugs — and, as the next episode shows, the first source of brand-new ones.

What you'll learn
  • Critical sections + mutual exclusion
  • Acquire / release discipline
  • Contention and the cost of locking
03
Episode 3 · Deadlock

When Both Threads Wait Forever

Two threads each hold a lock the other needs, and neither will let go — the program freezes forever. See the four conditions that must all hold for deadlock, the dining-philosophers picture of it, and the simple lock-ordering rule that makes it impossible.

What you'll learn
  • The four Coffman conditions
  • Circular wait + dining philosophers
  • Lock ordering to prevent it
04
Episode 4 · Threads vs Processes

Shared Memory or Safe Isolation?

Threads share memory and are cheap to switch between — great for speed, dangerous for safety. Processes are isolated and robust but heavier. Which you choose decides how work is shared and how far a single crash can spread.

What you'll learn
  • Shared vs isolated address spaces
  • Context-switch + memory cost
  • When to pick threads vs processes
05
Episode 5 · Async & the Event Loop

One Thread, Thousands of Connections

A single thread can juggle thousands of tasks by refusing to wait: fire off the I/O, move on to the next thing, and come back when the result is ready. The event loop is how one thread stays busy instead of blocked — the model behind Node, nginx and modern async runtimes.

What you'll learn
  • Blocking vs non-blocking I/O
  • The event loop + task queues
  • Why async isn't the same as threads
06
Episode 6 · Concurrency vs Parallelism

Dealing With vs Doing Many Things at Once

Concurrency is dealing with many things at once; parallelism is doing many things at once. One barista alternating between orders versus five baristas working in parallel — the distinction that clears up most of the confusion and tells you where more cores actually help.

What you'll learn
  • Interleaving vs simultaneous execution
  • When more cores help (and when they don't)
  • CPU-bound vs I/O-bound work
07
Episode 7 · The Actor Model · Finale

Stop Sharing Memory Entirely

The finale flips the whole problem: if nothing is shared, nothing can race. Actors own their private state and communicate only by sending messages to each other's mailboxes — so locks and races simply can't happen. It's the model behind Erlang, Akka and a lot of resilient distributed systems.

What you'll learn
  • Share-nothing + message passing
  • Mailboxes and one-at-a-time processing
  • Why actors scale across machines

Reasoned about the races? Now design with them.

Concurrency shows up the moment a system has more than one user. The system-design walkthroughs put these ideas to work — distributed locks, counters, queues and schedulers you can trace step by step.