A counter keeps its value in a slow external store (think: a row in a database or a key in a cache). The store has two methods:
store.read()returns the current value.store.write(value)replaces it.
Implement Counter(store) with one method:
increment() -> int: add 1 to the stored value and return the new value.
Many threads call increment() on the same Counter at once. Every call must count: after n calls the store holds start + n, and no two calls may return the same number.
store = ... # holds 0
c = Counter(store)
c.increment() # 1
c.increment() # 2
# 8 threads each calling increment() 50 times -> store holds 402,
# and the 400 returned values are exactly 3..402
The obvious version, v = store.read() + 1; store.write(v); return v, is a read-modify-write: two threads can both read 5 and both write 6, losing an update. The tests use a store that is slow enough to make that happen almost every time.
Constraints:
- If
store.writeraises an exception,increment()should let it propagate, and later calls must still work (the lock must not stay held). - Don't sleep or busy-wait.
Show hint
Guard the whole read-then-write with one threading.Lock created in __init__, using with self.lock: so it is released even when an exception is thrown.