← Назад к списку
ТехническаяPythonMiddle

Что такое GIL и как он влияет на многопоточность в Python?

Короткий ответ

  • GIL — глобальная блокировка интерпретатора в CPython
  • В один момент байткод выполняет только один поток
  • CPU-bound задачи в потоках не ускоряются
  • I/O-bound задачи ускоряются: GIL отпускается на время ожидания
  • Для CPU-нагрузки — multiprocessing или C-расширения
  • С Python 3.13 есть экспериментальная сборка без GIL (free-threaded)

GIL позволяет лишь одному потоку исполнять байткод, поэтому потоки помогают при I/O, а для CPU-задач нужны процессы или нативные расширения.

Как сказать вслух

пример ответа

GIL — это блокировка в CPython, из-за которой байткод в один момент времени выполняет только один поток, даже на многоядерном процессоре. Поэтому потоки не ускоряют вычисления, но отлично подходят для ожидания сети или диска — на время I/O блокировка отпускается. Для тяжёлых вычислений берут multiprocessing или библиотеки вроде numpy, которые считают вне GIL. Ещё упомяну, что начиная с Python 3.13 появилась экспериментальная сборка без GIL.

Подробный ответ

Основной ответ

GIL (Global Interpreter Lock) — мьютекс в CPython, который гарантирует, что байткод исполняет только один поток одновременно. Он упрощает управление памятью (подсчёт ссылок становится безопасным без мелких блокировок), но лишает потоки параллелизма на CPU. При I/O-операциях (сокеты, файлы, sleep) поток отпускает GIL, поэтому threading хорошо подходит для сетевых задач. CPU-bound код распараллеливают через multiprocessing (отдельные процессы со своими интерпретаторами) или через нативные расширения (numpy, Cython), которые освобождают GIL. В Python 3.13+ появилась официальная free-threaded сборка (PEP 703), где GIL отключаем, но она пока не является дефолтом.

Ключевые моменты

  • Зачем GIL вообще нужен. Он защищает внутренние структуры интерпретатора и счётчики ссылок, делая однопоточный код быстрым и простым.
  • I/O-bound vs CPU-bound. Выбор инструмента зависит от типа нагрузки: потоки и asyncio для ожидания, процессы для вычислений.
  • Обходные пути. multiprocessing, concurrent.futures.ProcessPoolExecutor, C-расширения и numpy выполняют работу вне GIL.
  • Актуальное состояние. PEP 703: free-threaded CPython доступен с 3.13 как отдельная сборка, экосистема постепенно адаптируется.

Практический контекст

Вопрос встречается почти на каждом собеседовании по Python. Интервьюер смотрит, может ли кандидат правильно выбрать инструмент: threading/asyncio для сетевых сервисов и парсеров, ProcessPoolExecutor для обработки данных. Частое продолжение — «почему потоки всё же полезны» и «что изменится без GIL». В реальной работе это выбор между воркерами uvicorn, пулом процессов для отчётов и очередями задач вроде Celery.

Частые ошибки

  • Утверждают, что потоки в Python «вообще бесполезны», забывая про I/O-bound задачи
  • Путают GIL с особенностью языка: это деталь CPython, в Jython или free-threaded сборке его нет
  • Думают, что GIL делает любой код потокобезопасным — гонки на уровне логики всё равно возможны

ИП Кочкин Алексей Сергеевич · ИНН 390509026279 · ОГРНИП 325390000030973 · jiniys2005@yandex.ru