foundation17 min studyLesson 4 in Engineering

Concurrency without confusing it with parallelism

Build a mental model of processes, shared state, queues, and the limits of adding workers.

On this page

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.

Xideal≤psX_{\rm ideal}\leq\frac{p}{s}
p workers each needing s seconds of exclusive service per job have an ideal throughput ceiling p/s jobs per second. The bound assumes independent workers and ignores coordination, shared bottlenecks, and arrival variation.↔ Scroll wide equations horizontally.

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.

S(p)≤1f+(1−f)/pS(p)\leq\frac{1}{f+(1-f)/p}
For fixed total work, Amdahl's ideal speedup bound uses serial fraction f and p parallel workers. Speedup is dimensionless. Communication and synchronization overhead can make real speedup smaller.↔ Scroll wide equations horizontally.

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 λ\lambda while holding service rate μ\mu fixed, then increase service. Its fluid backlog starts at four jobs and changes at rate λ−μ\lambda-\mu, 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.

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.

  1. Identify the serial fraction: 25 / 100 = 0.25. This part remains even with unlimited workers under the stated algorithm.

  2. 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.

  3. 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.

The result

Four workers do not imply fourfold acceleration. Improve the serial design or reduce overhead once those costs dominate.

Explore the model

Interactive lab

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.

Arrivals, service, and waiting workFluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Current readings: Fluid backlog: 4; Net rate · λ − μ: −1 /s; M/M/1 mean residence: 1 s. All parameters are adjustable with the labeled controls below.02.557.51001.534.56Elapsed time · sFluid backlogλ < μ
Fluid backlogCurrent time
Fluid backlog
4
Net rate · λ − μ
−1 /s
M/M/1 mean residence
1 s
t = 0 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.

Check your understanding

Why can two concurrent increments lose an update?

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.

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.