Тупики (deadlock) и защита от них
Что такое тупик
Тупик (deadlock, взаимная блокировка) — ситуация, когда несколько процессов (или потоков) навсегда ждут друг друга, и ни один не может продолжить работу.
Классический пример с двумя мьютексами:
Поток 1: lock(A) → ... → lock(B)
Поток 2: lock(B) → ... → lock(A)
Если оба захватили первый замок и ждут второй — вечное ожидание.
Связано: синхронизация и гонки, планирование, управление процессами.
Ресурсы и типы
Ресурс — всё, что выделяется в единственном экземпляре или ограниченно:
- мьютексы, семафоры, блокировки файлов;
- записи в таблице процессов;
- специальные устройства (принтер, лента);
- страницы памяти (в теории — при жёстком резервировании).
| Тип | Поведение |
|---|---|
| Исчерпаемый | Счётчик: N копий (семафор на N слотов) |
| Неисчерпаемый | Один владелец (мьютекс, принтер) |
Deadlock чаще формулируют для неисчерпаемых ресурсов с захватом/освобождением.
Четыре условия Кофмана (Coffman)
Тупик возможен только если одновременно выполнены все четыре:
- Взаимное исключение — ресурс в один момент у одного исполнителя.
- Удержание и ожидание (hold and wait) — держишь один ресурс, ждёшь другой.
- Невозможность принудительного отъёма — нельзя забрать ресурс без согласия владельца (процесс не «выгнали» с mutex).
- Циклическое ожидание — цепочка: P1 ждёт P2, P2 ждёт P3, … Pn ждёт P1.
Стратегия борьбы: разрушить хотя бы одно условие — тогда deadlock невозможен (в модели).
Граф ожидания (wait-for graph)
Узлы — процессы. Дуга P1 → P2 означает: P1 ждёт ресурс, удерживаемый P2.
- Если граф ацикличен — deadlock нет.
- Цикл — deadlock (для одного экземпляра каждого ресурса).
Для нескольких экземпляров (например, 3 принтера) используют расширенные модели; в учебниках часто начинают с одного экземпляра.
Пример на псевдокоде
Процесс 1: Процесс 2:
acquire(mutex_A) acquire(mutex_B)
acquire(mutex_B) acquire(mutex_A) // оба зависли
Исправление: глобальный порядок захвата — всегда сначала A, потом B:
acquire(mutex_A)
acquire(mutex_B)
// ...
release(mutex_B)
release(mutex_A)
Это разрушает циклическое ожидание (и часто hold-and-wait при дисциплине «захвати всё сразу»).
Стратегии обработки
1. Игнорировать (ostrich algorithm)
Используется там, где deadlock редок и дешевле перезапуск: некоторые embedded, прототипы. Не подходит для банковских транзакций.
2. Предотвращение (prevention)
Разрушить одно из условий Кофмана:
| Условие | Идея |
|---|---|
| Mutual exclusion | Спулинг принтера — очередь заданий, не прямой захват |
| Hold and wait | Захват всех ресурсов сразу перед работой (мало параллелизма) |
| No preemption | Отъём у процессов с низким приоритетом (редко для mutex) |
| Circular wait | Упорядочивание ресурсов (номера, lock ordering) |
На практике чаще всего — упорядочивание блокировок в коде.
3. Избежание (avoidance) — банкир (Banker's algorithm)
ОС знает максимальную потребность каждого процесса и текущее распределение. Перед выделением ресурса проверяет: останется ли система в безопасном состоянии (существует последовательность завершения всех процессов).
- Плюс: не допускает deadlock.
- Минус: нужны точные оценки потребности; консервативно; редко в полном виде в desktop ОС.
Полезно на экзамене и для понимания безопасного состояния.
4. Обнаружение и восстановление (detection & recovery)
Периодически строят граф ожидания. Если цикл —
- завершить один из процессов в цикле (rollback, освободить ресурсы);
- откатить транзакцию (СУБД);
- отобрать ресурсы (только если модель позволяет).
СУБД и некоторые серверы детектируют deadlock на блокировках строк и жертвуют одну транзакцию (victim selection по стоимости отката).
5. Таймауты
trylock с таймаутом — не гарантия отсутствия deadlock, но практическая защита: через N мс отказ и повтор/логирование. Риск: ложные срабатывания под нагрузкой.
Deadlock и планировщик
Deadlock — не то же самое, что «все процессы в очереди Ready». CPU может быть свободен, пока процессы заблокированы на mutex. Планировщик 5117 не «чинит» deadlock — нужна политика ресурсов.
Livelock — родственная проблема: процессы не блокированы, но бесполезно перестраиваются (оба отступают по вежливости) и не продвигаются.
Starvation — процесс ждёт бесконечно из-за приоритетов, без цикла с другими (не полный deadlock).
В Linux и Windows
- Ядро отслеживает lockdep (отладка), futex с цепочками ожиданий.
- Пользовательский код — ответственность разработчика;
pthread_mutexне предотвращает deadlock. - БД: InnoDB, PostgreSQL — detection + rollback транзакции.
- Файловые блокировки:
flock,fcntl— могут участвовать в deadlock при скриптах.
Инструменты: Thread Sanitizer (частично), helgrind, анализ дампов, echo w > /proc/sysrq-trigger (экстренная диагностика ядра — только для опытных админов).
Чек-лист для разработчика
- Минимизируйте число одновременно удерживаемых блокировок.
- Один порядок захвата для всех потоков.
- Короткие критические секции — см. 5118.
- Избегайте блокировок под другой блокировкой без схемы.
- Для иерархий — trylock + откат на уровне бизнес-логики.
- В распределённых системах — таймауты и идемпотентность повторов.
Резюме
| Термин | Смысл |
|---|---|
| Deadlock | Цикл «жду тебя, ты ждёшь меня» |
| Coffman | 4 условия — все нужны |
| Prevention | Запретить цикл (порядок lock) |
| Avoidance | Банкир — безопасное состояние |
| Detection | Найти цикл, убить/откатить |
Дальше: ввод-вывод, память и замещение страниц, чек-лист.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Программное обеспечение, управляющее аппаратными ресурсами компьютера. Основные функции и задачи ОС. Функциональные и нефункциональные требования к операционным системам, критерии выбора архитектуры ядра и способы реализации подсистем. Классификация операционных систем - ключевые семейства ОС, их отличия, типовые области применения и архитектурные особенности. Основы UNIX-систем - ключевые принципы многозадачности, иерархии файлов и управления процессами в классической Unix-модели. Ядро операционной системы - различия монолитной и микроядерной архитектуры, их компромиссы по производительности и надежности. Обзор Windows — версии, компоненты ядра NT, файловая система NTFS, структура каталогов и отличия от Unix-подобных систем. Полный инструментарий по Windows 11, возможности и функции. Устройство файловой системы Windows - иерархия хранения данных, служебные структуры и поведение файловой среды в ОС. Работа памяти в Windows - физические и виртуальные уровни, страницы памяти и механизмы управления ресурсами процессов. Локализация и символы в Windows - особенности кодировок, терминалов и корректной обработки текста в системных инструментах. Сравнение Windows и Linux - различия подходов к интерфейсу, администрированию и повседневным рабочим сценариям. Linux - структура файловой системы, ключевые каталоги и базовые принципы организации среды в Unix-подобной ОС.Операционные системы
Требования к ОС и подходы к реализации
Классификация операционных систем
Основы UNIX-систем
Ядро операционной системы
Windows
Справочник по Windows 11
Устройство файловой системы Windows
Работа памяти в Windows
Поддержка локализации и символов в Windows
Сравнение Windows и Linux
Linux