Every checkout request runs: read stock → wait L (network+DB round-trip) → write decision. Overselling happens whenever two requests read the same stock value before either one writes — both "see" an available unit and both succeed, driving the real count below zero.
No lock: write = decrement(stock) // unconditional
Optimistic CAS: write = if version==readVersion: decrement, version++
else: reject (conflict)
Pessimistic: resolveTime = max(now, lockFreeUntil) + L // strict FIFO
lockFreeUntil = resolveTime
Closed-form result (verified numerically, see below): because every request shares the same round-trip latency Ls, requests always resolve in the same order they spawn. That means the number of requests concurrently "in flight" at any instant is the pipeline depth N = rate × Ls. Under No Lock, once the counter is genuinely exhausted, exactly floor(N) requests are always caught mid-flight already holding a stale positive read — so total oversold converges to floor(rate × latency), independent of how large the starting stock was.
- No Lock — a naive "check quantity, then update quantity" checkout with no atomicity. The chart below plots stock level over time; watch it dive below the zero line by exactly the pipeline depth once the sale runs out.
- Optimistic (CAS) — a compare-and-swap on a version number: the write only commits if nobody else changed the row while this request was in flight. Never oversells, but a losing request must show "sold out" or retry, and conflict (rejection) rate rises with contention.
- Pessimistic (Lock) — a single mutex around the whole read-decrement-write, so requests are serialized. Never oversells either, but throughput is capped at 1/latency and a queue builds up under high request rates — visible as a growing "queue depth" readout and the swimlane backlog below.
Real-world relevance: this is exactly why mobile e-commerce flash sales (sneaker drops, ticket releases, limited restocks) either oversell without atomic inventory operations, or throttle/queue customers when they use one. Production systems typically use optimistic concurrency at the database row level (a version/ETag column) or a distributed lock / reservation-with-TTL scheme for high-contention SKUs.