Race Condition

Race Condition: когда миллисекунды решают всё

Привет, друг!

Race Condition (состояние гонки) — это когда два или больше потоков/процессов пытаются одновременно работать с общим ресурсом, и результат зависит от того, кто первый добежал. Звучит безобидно, но на практике это адская дыра в безопасности и стабильности систем.

Почему это критично

Представь: у тебя есть счётчик посетителей сайта. Два запроса приходят одновременно, оба читают значение 100, оба добавляют +1 и записывают 101. А должно быть 102. Теперь умножь это на банковские транзакции или систему бронирования билетов — вот где начинается веселье.

Классический пример на Python

Видишь проблему? Между чтением и записью есть окно уязвимости. Если другой поток успеет изменить counter в это время — твои данные полетели.

Эксплойт реального мира: TOCTOU

Time-Of-Check to Time-Of-Use — классика жанра. Проверяешь условие, потом используешь ресурс. Между этими моментами что-то меняется.

Атакующий между проверкой и созданием может подсунуть симлинк на /etc/passwd. Поздравляю, ты только что перезаписал системный файл.

Фикс: атомарные операции и блокировки

Блокировка гарантирует, что только один поток работает с переменной в момент времени.

Продвинутые техники

Атомарные операции через threading.atomic:

Использование семафоров для ограничения доступа:

Race Condition в веб-приложениях

Классический сценарий: проверка баланса перед покупкой.

Если юзер отправит два запроса одновременно, оба пройдут проверку до списания. Результат: купил два раза за цену одного.

Правильное решение:

Тут проверка и списание происходят атомарно на уровне базы данных.

Как ловить Race Conditions

Стресс-тестирование:

Race Detector в Go:

Python такого из коробки не имеет, но можно использовать ThreadSanitizer через C-расширения.

Защита файловой системы

O_EXCL + O_CREAT гарантируют, что файл создастся атомарно или упадёт с ошибкой, если уже существует.

Чеклист для защиты

  • Используй блокировки для критических секций
  • Атомарные операции на уровне БД (SELECT FOR UPDATE, ACID-транзакции)
  • Избегай TOCTOU — проверка и использование должны быть атомарными
  • Стресс-тестируй многопоточный код
  • Не полагайся на «это маловероятно» — в продакшене всё случается
  • Используй deadlock detection и timeout для блокировок

Реальный эксплойт: двойная трата

В 2010 году в Bitcoin была найдена уязвимость, где можно было потратить одни и те же монеты дважды из-за race condition в обработке транзакций. Патч вышел за часы, но это показало, что даже в критичных системах такие баги возможны.

Лайфхак: дебаг race conditions

Добавь случайные задержки в критические места:

Если с задержками всё падает — у тебя race condition. Теперь чини через блокировки.

Итого

Race Condition — это не теория, а реальная угроза. Каждая миллисекунда между чтением и записью — окно для эксплойта. Блокировки, атомарные операции и правильная архитектура — твоя броня. Никогда не полагайся на «быстродействие» как на защиту. В многопоточном мире скорость — твой враг, а синхронизация — твой друг.

Race Condition: когда миллисекунды решают всё

На этом все. Всем хорошего дня!