PythiloLesson 3 of 12 · progress kept in this browser

Race conditions and locks

Threads share memory. When two of them read, decide and write the same data, their steps can interleave, and one update overwrites the other. That is a race condition.

import threading

class Counter:
    def __init__(self):
        self.value = 0
        self.lock = threading.Lock()

    def add(self):
        with self.lock:
            self.value += 1

c = Counter()
threads = [threading.Thread(target=c.add)
           for _ in range(50)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print(c.value)  # 50

Even self.value += 1 is several steps: read, add, store, and a thread can be paused between them. A Lock lets one thread at a time into the block. with self.lock: acquires it and always releases it, even after an exception.

Your task

Fix Account so that deposit(amount) and withdraw(amount) are safe to call from many threads at once, using self.lock, and keep the pause in withdraw, which stands in for a slow database call. withdraw subtracts and returns True only if the balance covers amount; otherwise it returns False.

This lesson uses threads, which Python in this browser does not include. Read it here, and run and check it in the Pythilo app on iPhone or iPad.