Also known as: concurrency, parallelism
Concurrency is structuring a program so that multiple tasks can be in progress and advance independently; parallelism is actually running multiple computations at the same instant. Concurrency is about structure; parallelism is about execution, and the two are related but not the same.1
The distinction
Even on a single CPU core, a concurrent program can interleave work — run task A, pause it while it waits for I/O, switch to task B — so the tasks deal with progress together. Parallelism does several things at once and therefore requires multiple cores. You can have concurrency without parallelism (one core juggling tasks), and a good concurrency model makes tasks the runtime can also run in parallel when cores are available.1 As Rob Pike put it: concurrency is a way to structure things; if it works, parallelism may be a free bonus.
Models and the shared hazard
Languages offer different concurrency models: OS threads with locks, single-threaded async/await event loops, Go’s goroutines and channels, and the share-nothing actor model. What they are all really fighting is the data race — two tasks touching the same memory with at least one writing, with no synchronization, producing undefined results.1 Each model is, at heart, a different strategy for avoiding unsynchronized shared writes.
In practice
The right model follows the workload. I/O-bound work — waiting on networks or disks — favors async or lightweight tasks like goroutines; CPU-bound work like DSP favors real parallelism across cores; fault-tolerant systems favor actors. A streaming radio pipeline in Go runs capture, DSP, and decode stages concurrently and lets the runtime spread them across cores in parallel.
Sources
-
Concurrency (computer science) — Wikipedia, on concurrency as program structure versus parallel execution and the data-race hazard. ↩ ↩2 ↩3