ПрограммированиеBackend разработчик

Опишите модель работы с потоками в Python. Что такое GIL и как он влияет на параллелизм? Как решать задачи с параллельными вычислениями в Python?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

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

Это означает, что в CPython многопоточность не позволяет достигать реального параллелизма при выполнении Python-кода на уровне процессора; параллельность полезна только для задач, связанных с ожиданием (I/O-bound). Для CPU-bound задач рекомендуется использовать модуль multiprocessing, который запускает несколько процессов и обходит GIL.

Пример:

import threading def worker(): print('Start') # тяжелые вычисления print('End') threads = [threading.Thread(target=worker) for _ in range(5)] for t in threads: t.start() for t in threads: t.join()

Для параллелизма при интенсивных вычислениях применяйте multiprocessing:

from multiprocessing import Pool def square(x): return x*x with Pool(4) as p: print(p.map(square, [1, 2, 3, 4]))

Вопрос с подвохом.

Может ли многопоточность в Python ускорить выполнение compute-heavy задач?

Ответ: Нет, из-за GIL в стандартной реализации Python (CPython) потоки не дадут прироста производительности на CPU-bound задачах; для таких задач используйте multiprocessing или сторонние реализации интерпретатора (например, Jython, IronPython), не имеющие GIL.

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В проекте по обработке больших объёмов данных команда попыталась ускорить вычисления с помощью потоков (threading). Вместо ускорения время работы увеличилось, потому что GIL не давал потокам работать параллельно; после перехода на multiprocessing задача была решена.


История

Разработчик пытался одновременно скачивать большие файлы и обрабатывать их в нескольких потоках, но часто натыкался на "deadlock" из-за неосторожного использования общих переменных без блокировок (thread safety).


История

На backend-сервере были реализованы обработка тяжёлых запросов в thread-пуле. При росте нагрузки сервер начал "замирать" — выяснилось, что большинство времени потоки проводили в ожидании выполнения Python-кода из-за GIL, хотя запросы не были связаны с интенсивным I/O.