Skip to content

Asyncio Synchronization (Lock, Semaphore)

Why async locks exist

Even in a single-threaded event loop, tasks can interleave at awaitawait points.

So if a task:

  • reads shared state
  • awaits
  • writes shared state

…another task can run in-between.

asyncio.Lock

async_lock.py
import asyncio
 
 
lock = asyncio.Lock()
count = 0
 
 
async def inc():
    global count
    for _ in range(10_000):
        async with lock:
            count += 1
 
 
async def main():
    await asyncio.gather(inc(), inc())
    print(count)
 
 
asyncio.run(main())
async_lock.py
import asyncio
 
 
lock = asyncio.Lock()
count = 0
 
 
async def inc():
    global count
    for _ in range(10_000):
        async with lock:
            count += 1
 
 
async def main():
    await asyncio.gather(inc(), inc())
    print(count)
 
 
asyncio.run(main())

asyncio.Semaphore (limit concurrency)

async_semaphore.py
import asyncio
 
sem = asyncio.Semaphore(3)
 
 
async def worker(i: int):
    async with sem:
        print("start", i)
        await asyncio.sleep(0.2)
        print("end", i)
 
 
async def main():
    await asyncio.gather(*(worker(i) for i in range(10)))
 
 
asyncio.run(main())
async_semaphore.py
import asyncio
 
sem = asyncio.Semaphore(3)
 
 
async def worker(i: int):
    async with sem:
        print("start", i)
        await asyncio.sleep(0.2)
        print("end", i)
 
 
async def main():
    await asyncio.gather(*(worker(i) for i in range(10)))
 
 
asyncio.run(main())

πŸ§ͺ Try It Yourself

Exercise 1 – asyncio.Lock

Exercise 2 – asyncio.Semaphore

Exercise 3 – asyncio.Event

If this helped you, consider buying me a coffee β˜•

Buy me a coffee

Was this page helpful?

Let us know how we did