ConcurrencyPythonverifiedVerified

Mutex / Lock Pattern in Python

Guarantee that only one thread at a time can access a shared resource by requiring threads to acquire an exclusive lock before proceeding.

How to Implement the Mutex / Lock Pattern in Python

1Step 1: Implement the Mutex using asyncio.Lock

import asyncio


class Mutex:
    def __init__(self) -> None:
        self._lock = asyncio.Lock()

    async def acquire(self) -> None:
        await self._lock.acquire()

    def release(self) -> None:
        self._lock.release()

    async def with_lock[T](self, fn: ...) -> T:
        """Use as a context manager instead for idiomatic Python."""
        async with self._lock:
            return await fn()

2Step 2: Protect a shared counter with the mutex (context manager)

counter = 0
lock = asyncio.Lock()


async def increment() -> None:
    global counter
    async with lock:
        current = counter
        await asyncio.sleep(0.001)  # simulate async work
        counter = current + 1


async def main() -> None:
    global counter
    await asyncio.gather(*(increment() for _ in range(10)))
    print(counter)  # always 10


if __name__ == "__main__":
    asyncio.run(main())

Mutex / Lock Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Mutex / Lock Pattern in the Real World

A single-occupancy public restroom with a door latch is a perfect mutex. The latch (lock) ensures only one person (thread) occupies the restroom (critical section) at a time. Anyone who finds the door locked must wait outside; when the occupant leaves and unlatches the door, one waiting person may enter.