Сообщить об ошибке.

Global Interpreter Lock (GIL) в Python

Краткие сведения о GIL в Python

Global Interpreter Lock (GIL) в Python был представлен, чтобы сделать обработку памяти CPython проще и обеспечить наилучшую интеграцию с языком C (например, с расширениями).

GIL - это механизм блокировки (mutex), которая не позволяет нескольким потокам выполнить один и тот же байткод. Эта блокировка, к сожалению, является необходимой, так как система управления памятью в CPython не является потокобезопасной.

Краткие сведения о GIL:

  • Одновременно может выполняться только один поток.
  • Интерпретатор Python переключается между потоками для достижения конкурентности.
  • GIL применим к CPython (стандартной реализации). Но такие как, например, Jython и IronPython не имеют GIL.
  • GIL делает однопоточные программы быстрыми.
  • Операциям ввода/вывода, обычно GIL не мешает.
  • GIL позволяет легко интегрировать непотокобезопасные библиотеки на языке C
  • Благодаря GIL есть много высокопроизводительных расширений/модулей, написанных на языке C.

Для CPU зависимых задач интерпретатор делает проверку каждые N тиков и переключает потоки. Таким образом один поток не блокирует другие.

GIL это не проблема языка Python, а проблема реализации интерпретатора CPython. К счастью, в настоящее время существует несколько способов решения проблем GIL.

Многие видят слабость в GIL. Хотя это можно рассматривать это как благо, ведь были созданы такие библиотеки как |NumPy|, Pandas, которые занимают особое, уникальное положение в научном обществе.

GIL для каждого интерпретатора

Новое в Python 3.12

PEP 684 вводит GIL для каждого интерпретатора, так что теперь можно создавать вспомогательные интерпретаторы с уникальным GIL для каждого интерпретатора. Это позволяет программам на Python в полной мере использовать преимущества нескольких процессорных ядер. В настоящее время это доступно только через C-API, хотя ожидается, что Python API появится в версии 3.13.

Для создания интерпретатора с собственным GIL нужно использовать новую функцию Py_NewInterpreterFromConfig():

PyInterpreterConfig config = {
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
PyThreadState *tstate = NULL;
PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config);
if (PyStatus_Exception(status)) {
    return -1;
}
/* Новый интерпретатор теперь активен в текущем потоке. */