A thread lock coordinates access to a shared application invariant across cooperating threads.
Python locks: protect the complete inventory transition
Operation contract
The stock reservation holds its lock across the availability check and quantity decrement. Protecting only the assignment would still let two callers both observe the same remaining stock. Thirty callers each request one unit from twenty available units; accepted results and final stock are deterministic even though the identities of successful callers depend on scheduling.
Failure and ownership boundary
Every access to the invariant must follow the locking contract. A lock does not make unrelated direct field writes safe, and holding it during a remote call can stall all reservation work. This program does not assume a GIL makes a multi-step business transition atomic. Python inventory project: validate a batch before replacing stored state handles a different failure boundary: rejecting an entire multi-item request.
Working program
from concurrent.futures import ThreadPoolExecutor
from threading import Lock
class Stock:
def __init__(self, available):
self._available = available
self._lock = Lock()
def reserve_one(self):
with self._lock:
if self._available == 0:
return False
self._available -= 1
return True
def remaining(self):
with self._lock:
return self._available
stock = Stock(20)
with ThreadPoolExecutor(max_workers=4) as pool:
accepted = list(pool.map(lambda _: stock.reserve_one(), range(30)))
print(sum(accepted), stock.remaining())Output
20 0Costs and limits
The fixture does O(n) small transitions but serializes the shared state section. Locks can add waiting; no throughput claim follows from adding worker threads.
Common Mistakes
- Protect the check and mutation together.
- Do not hold this lock while waiting for an external service.
Connected lessons
Python thread pools: collect results and observe worker failures, Python inventory project: validate a batch before replacing stored state, Python asyncio.Queue: backpressure and completion accounting.
Follow the service contract
Python Condition: wait for protected state, not for a notification count.
