Получить доступ

Что такое GIL?

JuniorКонкурентность
Ещё спрашивают так:
  • Зачем в Python глобальная блокировка интерпретатора?
  • Почему потоки в Python не ускоряют вычисления?
  • Можно ли обойти GIL?
Коротко

GIL — блокировка в CPython: байткод Python в один момент выполняет только один поток.

  • CPU-задачи потоки не ускоряют, задачи ввода-вывода — ускоряют: GIL отпускается на ожидании
  • Для вычислений — процессы (multiprocessing) или C-расширения, отпускающие GIL (NumPy)

А ещё С Python 3.13 есть отдельная сборка без GIL (PEP 703), по умолчанию GIL остаётся

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

GIL (Global Interpreter Lock) — мьютекс внутри CPython. Поток должен держать его, чтобы выполнять байткод. Он упрощает управление памятью: подсчёт ссылок на объекты не нужно защищать отдельными блокировками, а C-расширения проще писать.

Что из этого следует:

  • вычисления (CPU-bound) в нескольких потоках идут не быстрее, чем в одном: потоки по очереди получают GIL;
  • ввод-вывод (сеть, диск, ожидание базы) — потоки помогают: на время ожидания поток отпускает GIL, и работают другие;
  • многие C-библиотеки (NumPy, обработка изображений, сжатие) отпускают GIL на время своих вычислений и параллелятся в потоках.

Как обойти для вычислений: multiprocessing или concurrent.futures.ProcessPoolExecutor — у каждого процесса свой интерпретатор и свой GIL; вынести тяжёлое в C, Cython или Rust.

GIL не делает код потокобезопасным: операции вида x += 1 состоят из нескольких шагов байткода, и поток может прерваться посередине. Общие данные всё равно защищают Lock.

GIL — особенность CPython. Начиная с Python 3.13 есть экспериментальная сборка без GIL (free-threaded, PEP 703), но стандартная сборка работает с GIL.

Пример

import threading
from concurrent.futures import ProcessPoolExecutor

def cpu_task(n):
    return sum(i * i for i in range(n))

# Потоки: CPU-задача не ускорится
threads = [threading.Thread(target=cpu_task, args=(10_000_000,)) for _ in range(4)]

# Процессы: настоящий параллелизм на нескольких ядрах
with ProcessPoolExecutor() as pool:
    results = list(pool.map(cpu_task, [10_000_000] * 4))

Что хотят услышать

  • Что такое GIL и в какой реализации он есть.
  • Разница влияния на CPU-bound и I/O-bound задачи.
  • Способы обойти: процессы, C-расширения.
  • GIL не заменяет блокировки для общих данных.

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

  • «В Python потоки вообще бесполезны» — для ввода-вывода они работают.
  • «GIL делает код потокобезопасным».

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем