Sobes.tech
Назад к вопросам
Junior — Middle
57

Какое количество потоков используется при выполнении различных корутин в библиотеке asyncio?

Компании, где спрашивали
Т-БанкТ-Банк

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

В asyncio корутины обычно выполняются в одном потоке — в том, где запущен event loop. Это не многопоточность, а кооперативная асинхронность: корутины переключаются только в точках await. Отдельные потоки появляются только если явно использовать threading, run_in_executor или другие механизмы вынесения работы.

Определение:

asyncio — это библиотека для асинхронного программирования, где задачи выполняются в одном потоке через событийный цикл. Разные корутины не создают отдельные потоки автоматически: они делят один и тот же поток выполнения и поочередно отдают управление при await. Если корутина делает блокирующую работу без await, она блокирует весь event loop.

Пример использования:

import asyncio

async def task(name, delay):
    print(f"{name} start")
    await asyncio.sleep(delay)
    print(f"{name} end")

async def main():
    await asyncio.gather(
        task("A", 1),
        task("B", 1),
        task("C", 1),
    )

asyncio.run(main())

В этом примере три корутины запускаются одновременно, но не в трёх потоках. Они работают в одном потоке и переключаются на await asyncio.sleep(...).

Пояснение кода:

Код показывает несколько корутин, которые ждут asyncio.sleep. Эта операция не блокирует поток, а передаёт управление event loop.

Шаги выполнения:

  1. asyncio.run(main()) создаёт и запускает событийный цикл.
  2. asyncio.gather(...) планирует три корутины.
  3. Каждая корутина печатает start и доходит до await asyncio.sleep(...).
  4. На время ожидания управление переходит другим корутинам.
  5. Через секунду все корутины завершают работу и печатают end.

Именно поэтому кажется, что они выполняются параллельно, хотя поток один.

Ключевые моменты:

  • По умолчанию asyncio использует один поток — поток event loop.
  • Корутины не создают новые потоки сами по себе.
  • Переключение между корутинами происходит только в точках await.
  • Блокирующий код внутри async def останавливает весь event loop.
  • Для настоящей потоковой/процессной параллельности нужны threading, run_in_executor, multiprocessing или аналогичные механизмы.