📝 Python

asyncio: Queue, Lock, Semaphore — синхронизация без потоков

P
Автор
Pyland
📅
Опубликовано
30.06.2026
⏱️
Время чтения
1 мин
👁️
Просмотров
116
🌳
Уровень
Продвинутый
🐦 💼 ✈️

В async коде несколько coroutines работают конкурентно в одном потоке. Между ними тоже могут быть race conditions — и asyncio предоставляет примитивы синхронизации.

asyncio.Queue — producer/consumer

import asyncio

async def producer(queue: asyncio.Queue, items: list):
    for item in items:
        await queue.put(item)
        print(f"Положили: {item}")
    await queue.put(None)  # sentinel — сигнал завершения

async def consumer(queue: asyncio.Queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print(f"Обработали: {item}")
        queue.task_done()

async def main():
    queue = asyncio.Queue(maxsize=3)  # буфер на 3 элемента
    await asyncio.gather(
        producer(queue, range(10)),
        consumer(queue),
    )

asyncio.Lock — защита от race condition

counter = 0
lock = asyncio.Lock()

async def increment():
    global counter
    async with lock:          # только одна coroutine за раз
        value = counter
        await asyncio.sleep(0)  # точка переключения
        counter = value + 1

async def main():
    await asyncio.gather(*[increment() for _ in range(100)])
    print(counter)  # всегда 100, не 87 или 63

asyncio.Semaphore — rate limiting

Самый частый use case: ограничить количество одновременных HTTP запросов.

import httpx

async def fetch(sem: asyncio.Semaphore, client, url):
    async with sem:           # максимум 5 одновременных запросов
        return await client.get(url)

async def main():
    sem = asyncio.Semaphore(5)
    async with httpx.AsyncClient() as client:
        results = await asyncio.gather(
            *[fetch(sem, client, url) for url in urls]
        )

asyncio.Event — одноразовый сигнал

ready = asyncio.Event()

async def server():
    await asyncio.sleep(1)  # инициализация
    ready.set()             # сигнал: готов

async def client():
    await ready.wait()      # ждём сигнала
    print("Подключились!")

async def main():
    await asyncio.gather(server(), client())

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

Event loop в Python: как asyncio делает «параллел…

Event loop — сердце asyncio. Он не запускает код параллельно в нескольких потоках. Он переключается...

📅 30.06.2026 👁️ 121
📝

pytest-django: тестирование Django

Охватываемые темы: Установка, @pytest.mark.djangodb, Фикстуры, Тестирование views.

📅 30.06.2026 👁️ 130
📝

pip: менеджер пакетов Python

Охватываемые темы: Установка пакетов, Обновление и удаление, requirements.txt, Виртуальное окружение.

📅 30.06.2026 👁️ 117

Понравилась статья?

Подпишитесь на наши обновления и получайте новые статьи первыми. Развивайтесь вместе с PyLand!