Что такое GIL в Python и каково его назначение

Ответ

GIL (Global Interpreter Lock) — это мьютекс (mutex) в стандартном интерпретаторе CPython, который разрешает исполнение Python-байткода только одному потоку (thread) в один момент времени.

Основное назначение:

  1. Защита управления памятью. GIL упрощает управление памятью в CPython, делая операции со счётчиками ссылок (reference counting) потокобезопасными без необходимости сложных блокировок на каждом объекте.
  2. Упрощение интеграции с C-библиотеками. Обеспечивает безопасность при работе с C-библиотеками, которые не являются потокобезопасными.

Ключевое следствие: Из-за GIL многопоточные программы на Python, которые интенсивно используют CPU (CPU-bound), не могут достичь истинного параллелизма на многоядерных процессорах. Потоки выполняются поочередно на одном ядре.

Пример демонстрации проблемы: Два потока, выполняющие CPU-bound задачу, работают не быстрее (а часто медленнее из-за накладных расходов на переключение контекста), чем один поток.

import threading
import time

def cpu_bound_task():
    count = 0
    for i in range(10**7):
        count += i

# Последовательное выполнение
start_time = time.time()
cpu_bound_task()
cpu_bound_task()
print(f"Sequential: {time.time() - start_time:.2f}s")

# Параллельное выполнение (в кавычках)
start_time = time.time()
thread1 = threading.Thread(target=cpu_bound_task)
thread2 = threading.Thread(target=cpu_bound_task)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(f"With threads: {time.time() - start_time:.2f}s")

Как обойти GIL? Для задач, требующих параллельных вычислений, используют модуль multiprocessing, который создает отдельные процессы, каждый со своим собственным интерпретатором Python и своим GIL. Для I/O-bound задач эффективно используется asyncio.