Operating Systems

Threads, Async & Event Loops

Threads inside a process, concurrency vs parallelism, threads vs async vs processes, and how C++, JavaScript/TypeScript and Python each map onto the OS.

The question this module answers · Why can a single core run a thousand tasks "at once", and why is that not parallelism?
Threads: Several Instruction Streams in One Process
▶ interactive

A thread is an independently scheduled instruction stream inside a process: it has its own stack, registers and instruction pointer, and shares everything else — heap, globals, descriptors — with its siblings, which makes threads cheap to create and communicate through, and easy to corrupt.

Process versus Thread
▶ interactive

Processes buy isolation at the price of expensive creation, expensive switching and explicit communication; threads buy cheap sharing at the price of shared failure — and every runtime, browser and database picks a point on that line for a reason.

Threads versus Async versus Processes

There are three ways to have many things in flight — a thread per task, an event loop that parks tasks while they wait, or a process per task — and the choice is decided by whether the work is CPU-bound or I/O-bound, how many tasks you need, and what it costs to have one of them fail.

Concurrency versus Parallelism
▶ interactive

Concurrency is having several tasks in progress at once, achieved on a single core by interleaving them in time slices; parallelism is executing several at the same instant, which requires several cores — a single core is always concurrent and never parallel.

How C++, JavaScript and Python Map onto the OS
▶ interactive

C++ exposes OS threads directly; JavaScript hides them behind an event loop per realm and reaches the OS through the runtime’s own threads; CPython wraps OS threads but serialises bytecode with the GIL in its default build — three different contracts over the same kernel.

The Event Loop
▶ interactive

An event loop is a single thread that repeatedly takes the next completed event from a queue and runs its handler to completion; the runtime and the OS do the waiting elsewhere, so one thread can hold thousands of in-flight operations as long as no handler blocks it.

Async I/O: What `await readFile()` Actually Does
▶ interactive

An `await` on an I/O call hands the request to the runtime, which hands it to the OS or a helper thread, frees the calling thread to run other work, and resumes the function as a continuation when the kernel reports completion — with mechanisms that differ between files and sockets and between Node, Python and C++.