Зачем интерпретатору одна общая блокировка
Речь прежде всего о CPython — самой распространённой реализации Python. В её обычной сборке глобальная блокировка интерпретатора, или GIL, разрешает выполнять Python-код только одному потоку в каждый момент времени. Потоки при этом не исчезают: планировщик регулярно передаёт им право работать, поэтому программа может переключаться между задачами.
Блокировка упрощает защиту внутреннего устройства интерпретатора. Например, объекты Python хранят счётчик ссылок — он помогает понять, когда объект больше никому не нужен и его память можно освободить. Если несколько потоков меняют такие данные одновременно, состояние может стать несогласованным. GIL не позволяет им делать это параллельно, снижая сложность синхронизации внутри CPython.
Когда потоки всё-таки помогают
Многопоточность полезна, если задача часто ждёт внешнего события: ответа сайта, чтения файла или данных от устройства. На время такого ожидания поток обычно уступает процессор другим задачам, а интерпретатор может разрешить другому потоку выполнять Python-код. Поэтому программа способна, например, ждать несколько сетевых ответов одновременно, не простаивая целиком из-за одного медленного соединения.
Иная картина у вычислений, которые долго и непрерывно выполняются в самом Python: обработка больших массивов обычными циклами или перебор вариантов. Несколько потоков не распределят такой код по ядрам процессора для одновременного исполнения. Переключение между ними может добавить накладные расходы, не ускорив расчёт.
Как обойти ограничение
Для настоящего параллелизма часто запускают несколько процессов. У каждого процесса свой интерпретатор и своя блокировка, поэтому они могут работать на разных ядрах; расплата — дополнительные расходы на память и обмен данными. Некоторые библиотеки выполняют тяжёлую работу в машинном коде и могут отпускать GIL, так что их вычисления не всегда подчиняются тому же ограничению, что циклы на Python.
Практический вывод зависит не от числа потоков, а от того, где уходит время: ожидание часто хорошо сочетается с потоками, а вычислительную нагрузку обычно приходится распределять иначе.






