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.

PipeShared memory
Data pathCopy into a kernel buffer, copy out on the other side (two copies, two syscalls)Both processes map the same frames — zero copies after setup
SynchronisationBuilt in: the writer blocks when full, the reader blocks when empty, EOF on closeNone: you bring a semaphore, futex, or lock-free ring buffer
ThroughputHundreds of MB/s to a few GB/s, bounded by copies and the 64 KB buffer (Linux default)Memory bandwidth; GB/s to tens of GB/s
SemanticsA byte stream (or a message queue with mkfifo/named pipes); one direction per pipeRaw bytes with whatever structure you impose; any direction
Setuppipe() before fork, or a named pipe (FIFO; Windows named pipes are message-capable)shm_open + mmap / memfd, System V shmget, Windows CreateFileMapping
Failure modeDeadlock when both sides fill their pipes; SIGPIPE when the reader diesCorruption from a missing lock; a crashed peer leaves a half-written structure
Choose this whenSimple producer-consumer between two processes, shell-style streaming, or when you want the kernel to do the flow control.High-volume or latency-critical exchange (database buffer pools, media pipelines, IPC between engines) and you can own the synchronisation.