Логотип YeaHub

База вопросов

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

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Python: synchronization, primitive

Зачем нужны примитивы синхронизации даже при наличии GIL?

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

Короткий ответ

GIL не защищает ваши данные — он защищает только внутренние структуры CPython. Потоки по-прежнему могут читать и изменять общие объекты почти одновременно, вызывая race conditions. Поэтому для корректного доступа к shared state используют Lock, RLock, Semaphore, Event, очереди сообщений и другие инструменты. Эти примитивы обеспечивают безопасную последовательность выполнения и гарантируют консистентность данных.

Длинный ответ

Многие считают, что наличие GIL делает многопоточность безопасной, но это заблуждение.

1. Что делает GIL, а что — нет

Определение:
GIL — глобальная блокировка интерпретатора CPython, разрешающая выполнение Python-байткода только одному потоку в конкретный момент времени.

GIL:

  • защищает внутренние структуры интерпретатора;

  • упрощает reference counting;

  • не гарантирует атомарность сложных операций Python-кода.

GIL не:

  • предотвращает логические гонки данных;

  • обеспечивает корректность модификации объектов на уровне бизнес-логики;

  • делает ваш код потокобезопасным.

2. Почему нужен контроль доступа к данным

Даже если поток выполняется «один за раз», переключение контекста может произойти в любой момент между операциями.

Например, операция counter += 1 не атомарна:

  1. чтение значения

  2. вычисление нового значения

  3. запись результата

Если два потока выполнят эти шаги «вперемешку», данные будут потеряны.

Python

import threading

counter = 0

def wrong():
    global counter
    for _ in 100_000:
        counter += 1  # неатомарно!

Этот код даст неправильный результат даже с GIL.

3. Примитивы синхронизации и их роль

  1. Lock / RLock

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

Python

lock = threading.Lock()

def safe():
    global counter
    with lock:
        counter += 1
  1. Semaphore

    • ограничивает количество потоков, которым разрешён доступ к ресурсу.

  2. Event, Condition

    • позволяют потокам ждать определённого состояния.

  3. Очереди (queue.Queue)

    • исключают общий доступ к mutable state.

4. Когда синхронизация особенно важна

  • при работе со структурами данных (списки, словари, множества);

  • при модификации общих объектов;

  • при наличии фоновых потоков, изменяющих состояние приложения;

  • при интеграции с I/O-операциями, где переключение потоков происходит часто.

5. Вывод

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

Уровень

  • Рейтинг:

    5

  • Сложность:

    6

Навыки

  • Python

    Python

Ключевые слова

#synchronization

#primitive

Подпишись на Python Developer в телеграм