Predict the output · Python

Two Checkouts, One Item Left

Easy Predict the output

Two requests run this checkout logic, interleaved as shown (generators stand in for concurrent requests). What does it print? Then fix it. See Lost Updates.

What does this print?

stock = {"sku": 1}
confirmed = []

def checkout(name):
    current = stock["sku"]          # SELECT stock
    yield                           # the other request runs here
    if current > 0:
        stock["sku"] = current - 1  # UPDATE stock = <computed>
        confirmed.append(name)

a, b = checkout("A"), checkout("B")
next(a)
next(b)
for request in (a, b):
    next(request, None)
print(stock["sku"], confirmed)
  1. 0 ['A']
  2. 0 ['A', 'B']
  3. -1 ['A', 'B']
  4. 1 []

Check your answer

Loading the editor… (JavaScript is required to run code in your browser.)

Solution

Show the answer

The output is:

0 ['A', 'B']

Both requests read 1 before either writes, so both pass the check and both write 0 — two confirmed orders for one item, and the stock never goes negative to warn you. That's a lost update. Fix it with an atomic conditional update (UPDATE … SET stock = stock - 1 WHERE stock >= 1, check affected rows), SELECT … FOR UPDATE, or a version check. See Lost Updates.