> Что такое дедлоки? (PHP)

Уровень: junior · Роль: backend · Язык: PHP · Категория: Технические вопросы

Компании: vanta

Стек: PHP

> Пример ответа

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

Дедлок - это ситуация, когда два или более процесса/потока блокируют друг друга, ожидая ресурсы, которые удерживает другой участник. Никто не может продолжить выполнение, и система зависает. В PHP это чаще встречается при работе с БД, файловыми блокировками или очередями. Классические условия возникновения - взаимное исключение, удержание и ожидание, отсутствие вытеснения и циклическое ожидание.

Подробное объяснение

Дедлок возникает, когда выполняются четыре условия Коффмана одновременно:

  1. Взаимное исключение - ресурс может использоваться только одним процессом за раз.
  2. Удержание и ожидание - процесс держит ресурс и ждёт другой.
  3. Отсутствие вытеснения - ресурс нельзя принудительно забрать.
  4. Циклическое ожидание - цепочка процессов, где каждый ждёт ресурс, удерживаемый следующим.

В контексте PHP дедлоки чаще всего проявляются на уровне БД (InnoDB row locks), файловых блокировок (flock) или распределённых систем (Redis locks). PHP сам по себе однопоточный, но при работе с очередями или воркерами несколько процессов могут конкурировать за одни ресурсы.

На практике

Типичный сценарий в PHP - два скрипта обновляют таблицы в разном порядке:

  • Скрипт A: UPDATE users ... затем UPDATE orders ...
  • Скрипт B: UPDATE orders ... затем UPDATE users ...

Если оба стартуют одновременно, A блокирует users, B блокирует orders, и оба ждут освобождения чужой блокировки. MySQL обнаружит дедлок через таймаут и откатит одну транзакцию, но в файловых блокировках PHP такого механизма нет - процесс зависнет навсегда.

Для предотвращения используют:

  • фиксированный порядок доступа к ресурсам;
  • таймауты на получение блокировок;
  • retry-логику при ошибках дедлока;
  • короткие транзакции.

Пример кода

PHP
// Пример дедлока на файловых блокировках
$fileA = fopen('/tmp/a.lock', 'c');
$fileB = fopen('/tmp/b.lock', 'c');
// Процесс 1
flock($fileA, LOCK_EX);
sleep(1); // имитация работы
flock($fileB, LOCK_EX); // зависнет, если процесс 2 уже держит b.lock
// Процесс 2 (в другом процессе)
flock($fileB, LOCK_EX);
sleep(1);
flock($fileA, LOCK_EX); // зависнет, если процесс 1 уже держит a.lock

Правильный подход - всегда блокировать файлы в одном порядке:

PHP
// Всегда сначала A, потом B
flock($fileA, LOCK_EX);
flock($fileB, LOCK_EX);

Как отвечать на собеседовании

Начни с определения, затем перечисли четыре условия Коффмана. Приведи пример из реальной практики - лучше всего с транзакциями БД, так как это ближе к backend-роли. Упомяни, что MySQL сам детектит дедлоки и откатывает одну из транзакций, а вот с файловыми блокировками нужно быть осторожнее. Заверши способами предотвращения: единый порядок доступа, таймауты, короткие транзакции.

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание базовых концепций конкурентности;
  • умение объяснить абстрактную проблему на конкретном примере;
  • знание инструментов PHP для работы с блокировками;
  • осознание разницы между дедлоком и обычной блокировкой;
  • практические навыки предотвращения дедлоков.

Типичные ошибки

  • Путать дедлок с обычным ожиданием блокировки - в дедлоке никто никогда не получит ресурс.
  • Говорить, что PHP не может иметь дедлоки из-за однопоточности - это неверно, так как речь о процессах и БД.
  • Не упоминать условия Коффмана - это базовый признак понимания темы.
  • Предлагать только один способ решения, например "просто добавить таймаут" - этого недостаточно.
  • Забывать, что MySQL сам разрешает дедлоки, а вот в файловой системе PHP такого механизма нет.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью