Как работает многопоточность в Python, ее особенности и ограничения
Что проверяют
Понимаете ли вы, что потоки настоящие, но глобальная блокировка не даёт им считать параллельно.
Как отвечать
Потоки в Python настоящие потоки операционной системы, создаются модулем threading. Но исполнять байткод одновременно они не могут: этому мешает глобальная блокировка интерпретатора. В каждый момент байткод исполняет один поток.
Отсюда главное разделение:
- вычислительные задачи: ускорения нет вовсе, а иногда становится хуже из-за накладных расходов на переключение;
- ввод-вывод: выигрыш есть, потому что блокировка освобождается на время системного вызова. Пока поток ждёт ответа сети или диска, остальные работают. То же касается расширений на C: библиотеки численных вычислений отпускают блокировку на время долгой операции.
Зачем блокировка существует: она сильно упрощает управление памятью через подсчёт ссылок и делает расширения на C безопасными по умолчанию. Цена этого и есть отсутствие параллельного счёта.
Важное уточнение: отсутствие параллелизма не означает отсутствия гонок. Переключение между потоками происходит между байткодами, поэтому даже простое увеличение счётчика не атомарно. Синхронизация нужна: Lock, RLock, Semaphore, Event, Condition, а лучше queue.Queue, которая берёт синхронизацию на себя.
Альтернативы под задачу:
multiprocessingили пул процессов для вычислений: у каждого процесса свой интерпретатор и своя блокировка. Цена это накладные расходы на передачу данных между процессами;asyncioдля большого числа сетевых операций: один поток и тысячи корутин дешевле тысяч потоков;- вынос вычислений в C: numpy и подобные библиотеки считают вне блокировки.
Про будущее стоит упомянуть: в версии 3.13 появился экспериментальный режим сборки без глобальной блокировки, и в 3.12 добавлены субинтерпретаторы со своими блокировками. Это направление развития, но по умолчанию картина пока прежняя.
Где спотыкаются
Считают, что из-за блокировки потоки бесполезны вовсе.
Ждут ускорения вычислений от потоков.
Не синхронизируют доступ, полагая, что блокировка защищает данные.
Не знают, что блокировка отпускается на операциях ввода-вывода.