В чем разница между мультитредингом и мультипроцессингом в Python
Что проверяют
Знаете ли вы, что такое GIL и как он меняет выбор между потоками и процессами. Следом обычно спрашивают, где тут asyncio и нужно ли синхронизировать потоки, если GIL уже есть.
Как отвечать
Базовое различие:
- потоки (
threading): живут в одном процессе и делят память. В стандартном CPython их сдерживает GIL: байткод Python в каждый момент выполняет только один поток. Во время ввода-вывода и в C-расширениях, которые его отпускают (numpy,hashlib, сжатие), GIL освобождается, поэтому потоки хорошо работают на I/O-bound задачах: запросы к API, чтение файлов, работа с базой; - процессы (
multiprocessing): у каждого свой интерпретатор, своя память и свой GIL, поэтому CPU-bound код идёт параллельно на всех ядрах. Плата: запуск процесса дороже, данные между процессами передаются через сериализациюpickle, общая память требуетmultiprocessing.shared_memoryилиManager.
Удобнее работать через concurrent.futures: ThreadPoolExecutor и ProcessPoolExecutor с одинаковым интерфейсом. Для большого числа сетевых соединений назовите третий путь, asyncio: один поток, кооперативная многозадачность, тысячи соединений без тысячи потоков.
Покажите, что следите за версиями. С Python 3.13 существует отдельная free-threaded сборка без GIL, в 3.14 она получила статус официально поддерживаемой, но по умолчанию интерпретатор по-прежнему с GIL, а часть библиотек к нему не готова. Также в 3.14 на Linux способ старта процессов по умолчанию сменился с fork на forkserver, на macOS и Windows давно используется spawn. Отсюда требование оборачивать запуск в if __name__ == "__main__":.
Где спотыкаются
Считают, что GIL делает код потокобезопасным. Операция counter += 1 не атомарна, потоки могут переключиться посередине, поэтому общие данные всё равно защищают threading.Lock или передают через queue.Queue.
Отправляют в ProcessPoolExecutor мелкие задачи. Если сериализация аргументов стоит дороже вычисления, процессы окажутся медленнее одного потока.
Говорят, что «в новом Python GIL убрали». Его можно отключить только в отдельной сборке, и об этом нужно говорить с оговорками про совместимость расширений.