В чем разница между многопоточностью, многопроцессностью и асинхронностью?
Что проверяют
Понимаете ли вы, что выбор диктует GIL и характер задачи: ждём или считаем.
Как отвечать
Начните с GIL: в CPython одновременно байт-код исполняет только один поток. Это и определяет всю картину.
asyncio, асинхронность. Один поток, кооперативное переключение на await. Подходит для операций ввода-вывода: тысячи сетевых запросов, веб-сервер. Переключение самое дешёвое, но любой блокирующий вызов или тяжёлый расчёт останавливает весь цикл.
threading, потоки. Настоящие потоки операционной системы, но GIL отпускается только на времени ожидания. Значит потоки помогают на вводе-выводе и почти не помогают на вычислениях. Плюсом идут гонки и необходимость блокировок.
multiprocessing, процессы. Отдельные интерпретаторы, у каждого свой GIL, поэтому это единственный способ реально загрузить несколько ядер вычислениями. Цена: память на процесс, стоимость запуска и обмен данными через сериализацию.
Правило выбора простое. Ждём сеть или диск, задач много: asyncio. Ждём, но библиотека синхронная и переписывать её нельзя: потоки. Считаем: процессы, а лучше библиотека, которая сама уходит из-под GIL, как NumPy.
Где спотыкаются
Берут потоки для ускорения вычислений и не получают выигрыша.
Считают, что asyncio даёт параллелизм.
Не знают, что операции NumPy и вызовы C-расширений отпускают GIL.
Не упоминают стоимость сериализации при обмене между процессами.