Как возникает гонка за общими данными

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

Представим счётчик со значением 10. Каждый процесс хочет увеличить его на единицу: сначала прочитать значение, затем прибавить 1 и записать результат. Если оба успеют прочитать 10 до того, как кто-либо запишет ответ, они оба вычислят 11. В итоге счётчик вырастет лишь на единицу, хотя операций прибавления было две.

Почему результат меняется от запуска к запуску

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

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

Как защищают общую запись

Один способ — блокировка: прежде чем менять данные, процесс получает временное право на доступ, а остальные ждут. Другой — атомарная операция, то есть действие, которое система выполняет как единое целое: например, увеличение счётчика без отдельного промежутка между чтением и записью.

В базах данных похожую роль играют транзакции — группы операций, которые сохраняются согласованно. Такие механизмы не ускоряют работу сами по себе: ожидание блокировки может замедлить систему. Но они не дают нескольким обновлениям незаметно перезаписать друг друга.