Гонка потоков в Python: почему print может вернуть False
@python_quizРазберем этот квиз
Коротко о задаче

Варианты ответа предлагали, будет ли этот код всегда печатать True, всегда False, может печатать и то, и другое, или упадёт с исключением. Разберёмся, что реально происходит и почему.
Почему результат недетерминирован
- Thread.start() создаёт и запускает поток асинхронно — управление возвращается сразу в вызывающий поток.
- print(flag) может выполниться до того, как другой поток выполнит присваивание.
- В CPython существует GIL (Global Interpreter Lock), но он не гарантирует порядок выполнения потоков и не устраняет гонки данных между потоками.
- В данном коде нет синхронизации, поэтому возможны оба сценария: основной поток печатает False (если ещё не произошло обновление), или печатает True (если второму потоку удалось выполнить обновление раньше).
Анализ вариантов ответов
- "Всегда выведет True" — неверно: нет синхронизации, присваивание может произойти позже.
- "Всегда выведет False" — неверно: поток может успеть изменить переменную до print.
- "Может вывести и True, и False" — верно в духе поведения программы: результат может быть разным в разных прогоновах и на разных системах.
- "Код упадёт с исключением" — неверно: вызов globals().update({'flag': True}) корректен и исключений не вызывает в этом контексте.
Демонстрация: эксперимент множеством прогонов

На практике в серии запусков вы часто увидите оба значения в счётчике — поведение зависит от планировщика потоков, скорости выполнения и платформы.
Как исправить (гарантировать True)
- Использовать join(), чтобы дождаться окончания потока:

- Использовать threading.Event для явной синхронизации:

- Для более сложных случаев — Lock, Condition или другие примитивы синхронизации.
Короткие рекомендации
- Не полагайтесь на порядок выполнения потоков без синхронизации.
- Для обмена состоянием между потоками используйте join, Event, Lock или очереди (queue).
- GIL не гарантирует отсутствие гонок и не даёт порядка между потоками — он лишь предотвращает одновременное исполнение байткода несколькими потоками в CPython.
Вывод
Без явной синхронизации поведение этого кода недетерминировано: в разных ситуациях он может печатать как True, так и False. Чтобы получить предсказуемое поведение, нужно дождаться завершения потока или использовать примитивы синхронизации.