Почему блокировка только записи не защищает check-then-act?

Почему блокировки только записи недостаточно? (check-then-act под замком) Контекст: конкуррентность и синхронизация потоков Если под замком находится только запись, сама проверка остаётся уязвимой к изменениям из…

Короткий ответ

Что ответить на собеседовании

Почему блокировки только записи недостаточно? (check-then-act под замком) Контекст: конкуррентность и синхронизация потоков Если под замком находится только запись, сама проверка остаётся уязвимой к изменениям из других потоков В промежутке между проверкой и действием (act) может возникнуть состояние гонки (race condition) Частичная блокировка способна привести к чтению устаревших либо неконсистентных данных Для защиты нужен общий атомарный блок check+act → это предотвращает TOCTOU (time-of-check-to-time-of-use) Применяются расширенные примитивы синхронизации (mutex, rw-lock) или транзакции Практический результат: корректность и…

Подробный разбор

Ответ с пояснениями

Почему блокировки только записи недостаточно? (check-then-act под замком)

  • Контекст: конкуррентность и синхронизация потоков
  • Если под замком находится только запись, сама проверка остаётся уязвимой к изменениям из других потоков
  • В промежутке между проверкой и действием (act) может возникнуть состояние гонки (race condition)
  • Частичная блокировка способна привести к чтению устаревших либо неконсистентных данных
  • Для защиты нужен общий атомарный блок check+act → это предотвращает TOCTOU (time-of-check-to-time-of-use)
  • Применяются расширенные примитивы синхронизации (mutex, rw-lock) или транзакции
  • Практический результат: корректность и консистентность данных, а также предотвращение логических ошибок и багов

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

Развёрнутый ответ

Основной ответ

В паттерне check-then-act (проверить — затем выполнить действие) нельзя ограничиваться блокировкой только записи. Между завершением проверки и началом действия может возникнуть состояние гонки (race condition). Если замок не удерживается на всём этом участке, другой поток или процесс успеет изменить данные после проверки, но до действия. В результате поведение становится недетерминированным, а данные могут быть повреждены.

Ключевые моменты

  • Проверку и действие необходимо выполнять атомарно: замок, установленный лишь на этапе действия, не предотвращает изменения данных после проверки.
  • Если между check и act нет блокировки, возникает риск race condition. Например, два процесса могут одновременно увидеть одно и то же состояние и попытаться выполнить одинаковое действие, что вызовет конфликт.
  • Более общее решение — заблокировать весь блок "check-then-act" либо применить атомарные операции или транзакции, например транзакцию в БД с Serializable Isolation Level.

Практический контекст

В многопоточных системах такая проблема часто появляется при обновлении счётчиков, проверке доступности ресурса и работе с пользовательскими кешами. В React 18 и Java Concurrent API для её устранения используют полные блокировки или атомарные классы, например AtomicBoolean. В распределённых системах с Redis применяют Lua-скрипты: вся операция check-then-act выполняется атомарно внутри Redis, а не защищается замком лишь частично.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку