Imagine putting a “Do not disturb” sign on a printer while it prints a file. Other tasks wait rather than mixing their lines into the same printout. A lock serves that purpose for a shared resource: a task acquires it before work begins and releases it when the work is done. section 8.3 section 8.4
The code that uses the shared resource is a critical section. Without protection, another task may enter while an operation is unfinished, causing a race condition. The operating-system scheduler cannot infer every application-specific rule, so the tasks must coordinate access. section 8.3 section 8.7
A mutex is a lock that gives one task exclusive access at a time:
- Acquire the mutex before entering the critical section. If another task holds it, wait until it becomes available. section 8.4
- Use the shared resource, then release the mutex so another task can proceed. section 8.4
# Chapter 8/race_condition/synced_bank_account.py
from threading import Lock
from unsynced_bank_account import UnsyncedBankAccount
class SyncedBankAccount(UnsyncedBankAccount):
def __init__(self, balance: float = 0):
super().__init__(balance)
self.mutex = Lock()
def deposit(self, amount: float) -> None:
self.mutex.acquire() #1
super().deposit(amount)
self.mutex.release() #2
def withdraw(self, amount: float) -> None:
self.mutex.acquire() #1
super().withdraw(amount)
self.mutex.release() #2
The Python account uses one threading.Lock around both deposit and withdrawal operations. Each operation acquires the mutex before changing the balance and releases it afterward, preventing concurrent transactions from interfering with one another. section 8.4
When one lock is not enough
In the dining-philosophers problem, each diner needs two chopsticks, each protected by a lock. If every diner holds one chopstick while waiting for the other, none can continue. Locks protect individual resources, but an unsafe pattern of acquiring several locks can stop progress. section 9.1
Locks also have a cost: acquiring and coordinating them adds work, and contention adds delays. An unreleased lock can leave other tasks waiting. When practical, avoid shared resources or use message passing; when sharing is necessary, protect the critical sections deliberately. section 9.1 section 9.10

















