Skip to content

The course

21 lessons in two tracks. The async track is the on-ramp and is meant to be finished first; the shared-memory track is what makes its explanations true.

Async

The event loop as a real mechanism, and the failure modes of code that awaits. Where nearly every learner actually lives, and the track to start with.

  1. 01Why a passing test proves nothingConcurrency is the one area where running the code a thousand times tells you almost nothing. What to do instead.8m
  2. 02The event loop, drawnThe call stack, the microtask queue and the macrotask queue, and the order they actually run in.12m
  3. 03Which one comes back firstTwo requests in flight, and the only thing in an event loop that is genuinely unordered.10m
  4. 04The gap inside an awaitChecking a condition and acting on it, with a suspension point in between. The cache that fills twice.14m
  5. 05Two writers, one recordRead, modify, write — across a network round trip, twice, at once.12m
  6. 06The promise nobody waited forWork started and not awaited, and the assertion that runs before it lands.10m
  7. 07The cancellation that does not cancelAn abort signal read once, before the work starts, and never again.12m
  8. 08Everything at onceMapping over a list with Promise.all, and what happens when the list is longer than the thing at the other end can take.12m

Shared memory

Locks, condition variables, semaphores and atomics. The classical material, and the vocabulary the async track has been borrowing all along.

  1. 01Two threads, one counterThe smallest possible race, the lock that fixes it, and what the lock actually costs.12m
  2. 02The bug that is there when the answer is rightA data race is a property of the program, not of the run. This is the case no test can catch, and the reason this app exists.12m
  3. 03The same bug, with a lock in the roomA check and an action that are each protected, and the gap between them that is not.12m
  4. 04DeadlockTwo locks, two threads, two orders, and a wait-for graph with a cycle in it.12m
  5. 05Waiting for something to be trueCondition variables, and why waking up is not a promise.14m
  6. 06A queue with a ceilingProducers, consumers, and the moment a full queue makes somebody wait.10m
  7. 07Doing it without a lockCompare-and-swap, the retry loop it needs, and the value that came back.14m
  8. 08Did it behave like one thing at a time?The right question to ask of a concurrent data structure, and the one that can actually be answered.12m
  9. 09Readers, writers and starvationA lock that lets readers share, and the writer that waits for a gap that never comes.10m
  10. 10Handing over something half-builtDouble-checked locking, and the difference between having a pointer and having the thing it points at.12m
  11. 11The result this checker says is impossibleTwo threads, four lines, and an outcome no interleaving produces — which real hardware produces anyway.12m
  12. 12Nothing runs in the order you wrote itWhy the compiler and the processor move your statements around, and what that means for code that publishes something.10m
  13. 13What the ordering arguments buyAcquire, release, and why every synchronising primitive in this course is really the same two ideas.10m
Everything you do here stays in this browser.