ENIGMA AI
ENIGMA AI

Из чего возникает эта проблема?

встречается 1× junior general

Как ответить

Race condition (состояние гонки) возникает, когда два или более параллельных процесса одновременно читают и записывают одно и то же изменяемое состояние без синхронизации. Результат работы становится непредсказуемым — он зависит от порядка, в котором операционная система или среда выполнения планирует операции. Чаще всего это проявляется в многопоточных программах, но и в однопоточном JavaScript с асинхронными коллбеками и общим состоянием может возникнуть логическая гонка, хотя и без data race.

Классический пример — инкремент счётчика:

let counter = 0;

function increment() {
    counter += 1;
}

// Запускаем две параллельные задачи
setTimeout(increment, 100);
setTimeout(increment, 100);

Операция counter += 1 на самом деле состоит из трёх шагов: чтение текущего значения, прибавление единицы, запись результата. Если два потока (в браузере — Web Workers с SharedArrayBuffer, в Node.js — Worker threads) выполнят эту операцию одновременно, возможен сценарий: оба читают 0, оба прибавляют 1 и записывают 1. Итоговое значение станет 1, хотя мы ожидали 2.

Основные причины, из которых возникает race condition:

  • Отсутствие синхронизации — критические секции не защищены мьютексами, атомарными операциями или локерами.
  • Неатомарные составные операции — read-modify-write, check-then-act и т.д.
  • Разделяемое состояние — разные потоки используют общие переменные, а не передают данные через message passing.
  • Предположение о порядке выполнения — код рассчитывает, что задача A завершится раньше задачи B, хотя это не гарантируется.
  • Повторное создание одинаковых событий (например, быстрый double-click отправляет два запроса, которые обрабатываются параллельно).

В веб-разработке race conditions часто встречаются в сценариях загрузки/сохранения: пользователь дважды нажимает кнопку «Отправить», и сервер обрабатывает оба запроса как независимые, создавая дубликаты. Или при загрузке данных с сервера — первый ответ ещё не обработан, а второй уже пришёл, и состояние UI разрушается.

Чтобы избежать проблемы, используют атомарные операции (в JS — Atomics.add, Atomics.store), мьютексы (через блокировки или специальные библиотеки), immutable-структуры или полное исключение общего состояния (каждый поток работает со своей копией). В UI-слое помогают флаги блокировки (дизаблим кнопку после первого клика) и идемпотентность операций на сервере.

Ключевые тезисы

  • Race condition возникает из-за одновременного доступа к общему изменяемому состоянию без синхронизации.
  • Составные операции (read-modify-write, check-then-act) не атомарны — между чтением и записью может вмешаться другой поток.
  • Порядок исполнения параллельных задач не детерминирован, полагаться на него нельзя.
  • В многопоточных средах (включая Web Workers с SharedArrayBuffer) data race возможен; в однопоточном JS — логическая гонка порядка коллбеков.
  • Основные методы борьбы: атомики, блокировки, immutable-данные, избегание shared state, идемпотентность и блокировка UI.

Что спросят дальше

  • — Какие инструменты или паттерны в JavaScript помогают синхронизировать доступ к общим данным в многопоточных сценариях?
  • — Как вы воспроизводите race condition, чтобы убедиться, что исправление работает? Приведите конкретный приём.
  • — Может ли race condition возникнуть в однопоточном JavaScript без Web Workers? Если да — в какой ситуации?

Готовьтесь к собеседованию с ENIGMA AI

AI-суфлёр подсказывает ответы прямо на собеседовании в реальном времени — незаметно для интервьюера.

Скачать приложение