Я шёл на интервью после пары постов про asyncio и думал, что «понял async». Первый вопрос — «в чём разница async и threading» — я ещё с грехом пополам проговорил. Потом спросили про GIL, event loop, и почему для моего «сложного расчёта» async не поможет. И я поплыл. Даже честное «честно, до конца не разобрался» прозвучало как признание провала. Обратно ехал злой и раздавленный.
Нейтрально и без паники. Разложить два мира:
- threading / многопоточность — больше «рабочих» в одном процессе; для задач, ждущих чего-то (опять же I/O) или вычислительных — но в CPython с GIL тяжёлые счётные поток в одно время не ускорить;
- async/await — один поток, который во время ожидания (сеть, база) переключается на другие задачи, не простаивая. Идеально для многих I/O-запросов, и не ускоряет чистое вычисление.
import asyncio, threading, time
def cpu_bound(n): # считает — поток на GIL не поможет
return sum(i * i for i in range(n))
async def io_like(t): # ждёт — async выигрывает
await asyncio.sleep(t)
return "ok"
# игрушечная иллюстрация разницы «ожидания» vs «счёта»
Стыд прошёл, когда я прочитал дальше и понял: я путал «когда использовать». Теперь держу правило: I/O → async подходит, сложный расчёт → потоки/процессы или подумать про алгоритм. Провал стал самым полезным уроком месяца — заставил закрыть дыру, о которой я и не подозревал. Хочется верить, что следующий разговор про это будет спокойнее.