Вопрос проверяет понимание модели выполнения Python (GIL) и её влияния на многопоточность, что важно для написания эффективных параллельных программ.
Хотя Python поддерживает создание потоков через модуль threading, его стандартная реализация CPython имеет архитектурную особенность — Global Interpreter Lock (GIL). Это механизм, который предотвращает одновременное выполнение байт-кода Python несколькими потоками в одном процессе.
GIL — это глобальный мьютекс (блокировка), который захватывается интерпретатором перед выполнением любого байт-кода Python. Он был введён для упрощения управления памятью в CPython, особенно для подсчёта ссылок — механизма сборки мусора. Без GIL несколько потоков могли бы одновременно изменять счётчик ссылок у одного объекта, что привело бы к повреждению памяти или утечкам. GIL делает CPython потокобезопасным на уровне интерпретатора, но ценой истинного параллелизма.
import threading
import time
def cpu_task(n):
count = 0
for i in range(n):
count += i
return count
# Запуск двух потоков на CPU-задаче
start = time.time()
threads = []
for _ in range(2):
t = threading.Thread(target=cpu_task, args=(100_000_000,))
t.start()
threads.append(t)
for t in threads:
t.join()
print(f"Время с потоками: {time.time() - start:.2f} сек")
# Скорее всего, время будет примерно таким же или даже больше,
# чем при последовательном выполнении из-за GIL и накладных расходов.Для достижения истинного параллелизма в CPU-задачах в Python используют:
multiprocessing): Создаёт отдельные процессы с собственным интерпретатором и памятью. Нет общего GIL.asyncio): Эффективно для I/O-задач, использует один поток, но множество корутин.Вывод: Python (CPython) считается однопоточным из-за GIL, который сериализует выполнение байт-кода потоками. Это ограничение критично для CPU-связанных задач, где стоит использовать многопроцессность. Для I/O-задач потоки или асинхронность остаются эффективными подходами.