Всех с наступившим! 🐌
Решил я тут почитать, что умные дядьки пишут про дедлоки. Как обычно оказалось, что поверхностное понимание уровня «пройти интервью» неверно от начала до конца, а в реальности всё супер интересно и конечно известно уже последние лет 50.
Дедлок или deadly embrace, как их называл товарищ Дейкстра (тот самый, который алгоритм) — ситуация бесконечного ожидания, при которой группа процессов не может продолжать работу, пока «внешние силы» не совершат определенные действия. Слово «процесс» здесь не имеет отношения к процессам в операционной системе. Процесс в дедлоке — некий автомат с набором состояний. Такими состояниями могут быть «процесс А не владеет ресурсами» или «процесс B владеет ресурсом alpha и пытается получить ресурс beta». На самом деле определение не совсем корректное в 100% ситуаций, но для обсуждения большинства подходов подойдёт.
Для начала, рассмотрим самый простой случай: дедлок на одной машине, вызванный конкурентным доступом к некоторому ресурсу из нескольких процессов. Ресурсом может быть как примитив синхронизации, например мьютекс, так и устройство, например принтер.
Такой дедлок называется либо ресурсным, либо interleaved дедлоком. Первое более привычное и популярное название, второе я нашёл только в [4]. Для возможности его возникновения необходимо выполнение 3 условий:
1. Exclusive access. Только один процесс может захватить ресурс одновременно.
2. No-preemption. Процесс, захвативший ресурс, не может быть прерван.
3. Hold and wait condition. Должны разрешаться ситуация, при которой процесс захватил сначала один ресурс, а теперь ждёт пока освободится второй. Не отпуская при этом первый.
Наличие этих условий в системе ещё не гарантирует возникновение дедлока! Это только необходимые условия. Их наличие означает существование unsafe region[5] — такого набора состояний процессов, попав в которое, ни один из процессов не может завершить свою работу.
При наличии unsafe region достаточно найти лишь 1 набор состояний, чтобы обеспечить дедлок. Оно же последнее условие:
4. circular wait condition. Процессы и ресурсы должны иметь возможность собираться в «цепочку». К примеру: Процесс A владеет ресурсом a при этом хочет захватить ресурс b, которым владеет процесс B, который хочет завладеть ресурсом a. Если обозначить эти отношения стрелочками:
a -> A значит процесс A владеет ресурсом a. A -> b значит процесс A хочет завладеть ресурсом b.Схематично получится круг (ну или квадрат):
a -> A
^ |
| v
B <- b