Что такое состояние гонки (race condition)?

«Что такое состояние гонки (race condition)?» — вопрос из категории Безопасность, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Состояние гонки (race condition) — это ошибка проектирования многопоточной или распределенной системы, при которой конечный результат выполнения зависит от непредсказуемого порядка выполнения параллельных процессов или потоков, обращающихся к общим данным. Это классическая проблема параллелизма.

Упрощенный пример на PHP (имитация проблемы в контексте веб-запросов): Представьте скрипт, который увеличивает значение счетчика в файле или БД.

// script.php (вызывается двумя запросами почти одновременно)
$counter = (int) file_get_contents('counter.txt');
// Запрос 1 читает значение 10.
// Запрос 2 ТАКЖЕ читает значение 10, прежде чем Запрос 1 запишет новое.
$counter++;
// Оба запроса вычисляют значение 11.
file_put_contents('counter.txt', $counter);
// Оба запроса записывают 11, хотя должно было быть 12.

Методы предотвращения в контексте веб-разработки и БД:

  1. Атомарные операции в БД:
    UPDATE counters SET value = value + 1 WHERE name = 'page_views';
  2. Пессимистическая блокировка:
    START TRANSACTION;
    SELECT * FROM accounts WHERE id = 1 FOR UPDATE; -- Блокировка строки
    -- ... выполнение операций ...
    COMMIT;
  3. Оптимистическая блокировка: Использование версии или временной метки для проверки, не изменились ли данные с момента чтения перед записью.
  4. Использование очередей (например, RabbitMQ, Redis): Сериализация операций, которые должны выполняться строго последовательно.
  5. Мьютексы и семафоры на уровне приложения (например, с помощью расширения ext-sync или блокировок на основе Redis/APCu для распределенных систем).

Состояния гонки сложно отлаживать, потому что они проявляются нестабильно. Ключ к решению — идентификация общих ресурсов и применение правильных механизмов синхронизации.