Concurrency vs Parallelism
Concurrency is dealing with many things at once; parallelism is doing many things at once.
Concurrency is about structure: a program makes progress on several tasks by interleaving them, even on a single CPU core. A web server waiting on a database can serve another request in the meantime.
Parallelism is about execution: tasks literally run at the same instant on multiple cores or machines. Rendering video frames on eight cores is parallel work.
Most back-end services are concurrency-bound (waiting on I/O), not CPU-bound. That is why async I/O often improves throughput more than adding cores.
Diagram
Key concepts
- Thread
- A unit of execution scheduled by the operating system. Threads share memory inside a process.
- Async / await
- Lets a thread start an I/O operation and do other work until it completes, instead of blocking.
- Race condition
- A bug where the result depends on the timing of concurrent operations on shared state.
- Lock / mutex
- Ensures only one thread enters a critical section at a time. Correct, but can reduce throughput.
- Amdahl’s law
- The serial part of a workload limits how much speed-up parallelism can deliver.
Trade-offs
Benefits
- Concurrency keeps CPUs busy while waiting on I/O
- Parallelism shortens CPU-heavy jobs
- Both increase throughput when applied to the right bottleneck
Costs
- Shared state introduces races and deadlocks
- Harder to test and reproduce bugs
- Thread overhead and context switching cost CPU and memory
Use it when
- Concurrency: APIs, web servers, anything that waits on network or disk
- Parallelism: image processing, data transforms, report generation, ML inference batches
Common mistakes
- Blocking on async code (
.Result,.Wait()), which can starve the thread pool - Adding threads to a database-bound service — the database becomes the queue
- Mutating shared collections without synchronisation
Interview questions
Q1Can you have concurrency without parallelism?
Q2Why does async I/O improve API throughput?
Q3How would you avoid a race condition on a shared counter?
Interlocked.Increment), a lock around the update, or avoid shared state by giving each worker its own counter and summing at the end.Related lessons
Big-O Notation & Time Complexity
A shared language for how the cost of an algorithm grows as its input grows.
FoundationsLatency Numbers & the Memory Hierarchy
Rough timings for memory, disk and network that make back-of-the-envelope design possible.
Messaging & MicroservicesMessage Brokers: RabbitMQ vs Kafka vs ActiveMQ
Queues and logs for decoupling services — and how the three popular brokers differ.