Перейти к содержимому
На этой странице

Многопоточность и многопроцессорность

Все темы Python Developer

Что такое GIL (Global Interpreter Lock)?

GIL в обычной сборке CPython допускает выполнение байт-кода только одним потоком за раз в одном интерпретаторе. При блокирующем вводе-выводе и в некоторых расширениях на C он освобождается. Это ограничивает параллелизм вычислений на Python, но не исключает полезную многопоточность. Начиная с CPython 3.13 доступны отдельные free-threaded сборки без GIL.


В чем отличие multiprocessing от multithreading в Python?

Отличие между multiprocessing и multithreading в Python заключается в том, как они обрабатывают параллелизм:

Multiprocessing:

  • multiprocessing позволяет создавать отдельные процессы для выполнения задач.

  • Каждый процесс имеет свое собственное пространство памяти, что делает его более надежным при работе с разделяемой памятью и предотвращает проблемы с GIL.

  • Это подходит для CPU-интенсивных задач, которые могут быть распараллелены, так как каждый процесс может использовать отдельное ядро процессора.

Multithreading:

  • multithreading создает несколько потоков внутри одного процесса для выполнения задач.

  • Потоки разделяют общее пространство памяти процесса, что может привести к проблемам с синхронизацией доступа к общим ресурсам.

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

В целом, multiprocessing обеспечивает большую изоляцию и параллелизм, в то время как multithreading может быть эффективным для задач, требующих ввода-вывода, но может столкнуться с проблемами с синхронизацией при доступе к общим ресурсам.


Каковы различия между IO-bound и CPU-bound задачами?

Различия между IO-bound и CPU-bound задачами связаны с тем, какие ресурсы больше всего использует каждая из них:

IO-bound задачи:

  • Эти задачи в основном зависят от операций ввода-вывода (IO), таких как чтение и запись файлов, сетевые запросы и т. д.

  • Примеры IO-bound задач включают загрузку веб-страниц, чтение больших файлов, обращение к базам данных и т. д.

  • В таких задачах основное время ожидания затрачивается на ожидание завершения операций ввода-вывода, а не на обработку данных.

CPU-bound задачи:

  • Эти задачи требуют большого количества вычислительных ресурсов процессора (CPU).

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

  • В таких задачах основное время затрачивается на обработку данных или выполнение алгоритмов, а не на ожидание операций ввода-вывода.


Где лучше использовать потоки и асинхронность в Python?

Потоки подходят для конкурентного выполнения блокирующего ввода-вывода, особенно если библиотеки имеют синхронный API. В обычной сборке CPython GIL мешает потокам параллельно выполнять CPU-bound код на Python, поэтому для тяжёлых вычислений чаще используют процессы. Исключения: расширения, которые освобождают GIL, и free-threaded сборки Python.

asyncio удобно для большого числа одновременно ожидающих операций, если весь стек поддерживает неблокирующий async API. Оно работает в одном потоке, переключая корутины в точках await, поэтому блокирующий вызов внутри event loop останавливает остальные задачи.

Подробнее: потоки и asyncio в документации Python.


Почему GIL не устраняет гонки данных?

GIL в обычной сборке CPython разрешает исполнять Python bytecode одному потоку за раз, но составная операция состоит из нескольких шагов, между которыми возможно переключение; C-расширение также может отпустить GIL. Поэтому read-modify-write общего объекта остается гонкой. Критическую секцию защищают Lock или убирают совместное изменяемое состояние. Free-threaded CPython делает зависимость от GIL еще менее допустимой. Корректность проверяют под конкуренцией и при завершении процесса, потому что последовательный тест не обнаруживает гонку.


Как процессам безопасно разделять данные?

Процессы имеют раздельную память. Небольшие сообщения безопаснее передавать через multiprocessing.Queue или pipe с ценой сериализации. Для больших буферов подходит shared memory, а Value и Array дают простые разделяемые значения; доступ к составному состоянию синхронизируют Lock или Semaphore. Manager удобен, но прокси и отдельный server process дороже. Владелец и жизненный цикл shared segment должны быть явными. Корректность проверяют под конкуренцией и при завершении процесса, потому что последовательный тест не обнаруживает гонку.


Как выбрать примитив синхронизации потоков?

Lock защищает одну критическую секцию, RLock допускает повторный вход того же потока, Semaphore ограничивает число одновременных владельцев ресурса. Event сообщает факт наступления состояния, а Condition позволяет ждать предикат под общей блокировкой и перепроверять его в цикле. Примитив выбирают из протокола взаимодействия. Он не исправляет слишком крупную общую mutable-state модель и может добавить дедлоки. Корректность проверяют под конкуренцией и при завершении процесса, потому что последовательный тест не обнаруживает гонку.

Собеседования: Python

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: Python-разработчик, Backend-разработчик на Python. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.