Compare

Side-by-side on the decisions that recur: process vs thread, threads vs async, mutex vs semaphore, blocking vs non-blocking I/O, container vs VM — with when to choose each.

Blocking I/ONon-blocking / async I/O
`read()` with no dataThe thread sleeps in the kernel until data arrivesReturns EAGAIN/EWOULDBLOCK at once (non-blocking), or completes later via a notification (async)
Concurrency modelOne thread per in-flight operationOne thread drives many operations via readiness (epoll/kqueue) or completion (IOCP, io_uring)
CPU while waitingZero — the thread is off the run queueZero if you wait on readiness; 100% if you spin retrying EAGAIN
SimplicityStraight-line code; errors are return valuesState machines, callbacks or coroutines; partial reads and writes are normal
Files vs socketsRegular files always "block" on the page cache/disk on Linux — O_NONBLOCK does nothing for themSockets and pipes multiplex well; true async file I/O needs io_uring, Windows overlapped I/O, or a thread pool (libuv)
Failure modeA slow peer holds a whole thread; thread pool exhaustionA forgotten non-blocking flag turns the loop into a blocking loop; busy-poll at 100% CPU
Choose this whenFew concurrent operations, simple tools and scripts, or a dedicated thread per long-lived operation is affordable.Many concurrent operations per thread — servers, proxies, event-loop runtimes — where waiting must not cost a thread.