Exercise: Lost Updates
This exercise puts the lost-update race lesson into code.
Scenario
Model the classic lost-update race as an explicit, deterministic interleaving of read-modify-write steps. There is one shared account whose balance starts at 100 and whose version number starts at 0. Commands arrive one at a time in a single thread — this is a deterministic simulation of the race, not actual concurrent execution.
Commands
| Command | Behavior | Output |
|---|---|---|
["read", txn] | Record a snapshot of the current balance and version for transaction txn | "<txn> read <balance>@v<version>" |
["write", txn, delta] | Commit txn: succeeds only if the shared version still matches the snapshot version | On success: "<txn> wrote <newBalance>@v<newVersion>"; on version mismatch: "<txn> conflict"; if no snapshot was taken first: "<txn> no snapshot" |
["balance"] | Report the current balance without modifying anything | "Balance: <balance>" |
On a successful write the balance becomes the snapshot balance plus the delta, the version increments by one, and the snapshot is discarded. A failed write leaves the balance and version unchanged.
6 read T1 read T2 write T1 50 balance write T2 -20 balance
T1 read 100@v0 T2 read 100@v0 T1 wrote 150@v1 Balance: 150 T2 conflict Balance: 150
Both T1 and T2 read the account at version 0, each capturing a snapshot of balance 100. T1 writes first: its snapshot version (0) matches the current version (0), so the balance becomes 150 and the version advances to 1. T2 then attempts to write: its snapshot version (0) no longer matches the current version (1), so it returns a conflict instead of silently overwriting T1's result. The balance stays at 150 throughout, demonstrating the lost-update detection the exercise is designed to show.
Your task
Implement the skeleton in the editor below so the commands produce the output described above.