Concurrency without confusing it with parallelism
Build a mental model of processes, shared state, queues, and the limits of adding workers.
On this page
The question for today
What you’ll understand
- Distinguish concurrent progress from simultaneous execution.
- Explain why a read-modify-write operation can race.
- Estimate worker capacity while acknowledging serial work and queueing.
Several requests can be in progress even when one processor executes only one instruction stream at a time. Concurrency organizes overlapping work; parallelism executes work simultaneously. AI infrastructure needs both, but adding workers can introduce synchronization, copying, and contention. A useful design makes ownership and coordination explicit before celebrating a larger worker count.
Choose an execution and ownership model
A process has an execution context and a virtual address space. Threads within a process share memory, while separate processes commonly exchange messages or use explicitly shared mappings. These are useful organizing models, not complete isolation guarantees. Runtime behavior varies: language implementations and native libraries can impose or release execution constraints. Check the actual runtime rather than assuming every thread always runs CPU-heavy work in parallel.
Asynchronous I/O allows a task waiting for an external event to yield so other work can progress. It is especially useful when requests spend time waiting on storage or networks. It does not make a CPU-bound calculation disappear. A long blocking calculation on an event loop can delay unrelated tasks. Separate the time spent computing, waiting, serializing, and coordinating before choosing threads, processes, asynchronous tasks, or a combination.
Shared mutation needs a correctness story
Suppose two workers read the same counter value, each adds one locally, and each writes the result. Both may write the same value, losing one increment. The program can look correct when executed slowly and fail under a different interleaving. A lock, an appropriate atomic operation, a transactional update, or single-owner message processing can address this particular problem, depending on the system's guarantees.
A bounded queue separates producers from consumers and makes overload visible. When producers outrun consumers, queued work accumulates until something changes. Backpressure asks upstream work to slow down; rejection prevents unlimited accumulation; cancellation avoids spending capacity on results nobody needs. Each policy affects users differently. Establish maximum queue age and memory consumption rather than treating an ever-growing queue as evidence that requests are safely handled.
Count the serial bottleneck and the overhead
A data-loading job might parallelize image decoding yet keep a single serial writer. Eventually the writer becomes the bottleneck. More decoders then increase queued memory rather than completed records per second. Separate-process workers may also serialize and copy inputs, and excessive parallelism can compete for memory bandwidth. The best worker count is a property of the workload and machine, not a universal number copied from a tutorial.
In the queue lab, increase arrival rate while holding service rate fixed, then increase service. Its fluid backlog starts at four jobs and changes at rate , clipped at zero. This is not an operating-system scheduler or a proof of fairness. The separately labeled M/M/1 residence-time formula assumes Poisson arrivals, exponential service times, one server, and a stable rate balance. Use it to explain why extra waiting work does not automatically increase throughput, and identify which real measurements would distinguish a CPU bottleneck from an external dependency.
Work it through
Four workers cannot remove a serial quarter
A fixed job takes 100 seconds on one worker. Twenty-five seconds are inherently serial; the other 75 seconds divide perfectly across workers in this model.
Identify the serial fraction: 25 / 100 = 0.25. This part remains even with unlimited workers under the stated algorithm.
With four workers, the parallel part takes 75 / 4 = 18.75 seconds. Add the unchanged 25 seconds to obtain an ideal total of 43.75 seconds.
Divide 100 by 43.75 to obtain a speedup near 2.29. Even unlimited workers cannot beat 25 seconds unless the serial part changes; actual coordination costs further reduce the gain.
Four workers do not imply fourfold acceleration. Improve the serial design or reduce overhead once those costs dominate.
The living notebook
Explore the model
Interactive lab · queue
Arrivals, service, and waiting work
Change arrival rate λ and service rate μ. The fluid backlog is max(0,4+(λ−μ)t); pause or step to inspect it. The separate M/M/1 mean needs its stated stochastic assumptions and λ<μ. Neither model simulates scheduling or lock contention.
- Fluid backlog
- 4
- Net rate · λ − μ
- −1 /s
- M/M/1 mean residence
- 1 s
Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA persistent arrival-service imbalance grows waiting work; the queue itself adds no service capacity.
Pause & reason
Check your understanding
Your turn
Try it yourself
Three independent workers each need 0.2 seconds per job. Estimate their ideal throughput ceiling, then explain why 20 arrivals per second are a problem.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Calculate jobs per second for one worker and multiply by three.
Compare with the solution
Each worker can complete five jobs per second, giving an ideal ceiling of 15 jobs per second. Sustained arrivals of 20 jobs per second exceed that capacity by five jobs per second; without rejection or backpressure, backlog grows. Variation and coordination can reduce usable capacity further.
Keep the idea
Take it with you
- Concurrency organizes overlap; parallelism supplies simultaneous execution.
- Shared mutation requires explicit synchronization or ownership.
- Worker counts must be evaluated against serial work, overhead, and overload policy.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.