Вопрос проверяет понимание различий между блокирующим и неблокирующим вводом-выводом.
Асинхронный код использует неблокирующие операции. Вместо ожидания данных он регистрирует интерес к событию. Когда данные появляются, event loop получает уведомление. Пока данных нет, выполняются другие задачи. Поэтому поток не блокируется.
Блокировка возникает, когда поток ждёт завершения операции.
В обычном коде вызов recv:
останавливает поток
ждёт данные
ничего больше не выполняется
Это плохо масштабируется при большом числе соединений.
В асинхронной модели:
сокет переводится в неблокирующий режим
recv не ждёт данные напрямую
event loop следит за готовностью сокета
Если данных нет:
корутина приостанавливается
управление возвращается loop
ОС уведомляет:
«сокет готов к чтению»
«данные появились»
Только после этого корутина продолжает выполнение.
Корутина вызывает await recv
Event loop регистрирует сокет
Поток освобождается
При событии задача возобновляется
Асинхронный код не блокируется, потому что он ждёт не данные, а событие от операционной системы.