Дана схема распределения ресурсов в ОС: три процесса P1, P2, P3; ресурсы R1 (1 экз.), R2 (1 экз.), R3 (1 экз.); текущие выделения и ожидания: P1 удерживает R1 и ждёт R2; P2 удерживает R2 и ждёт R3; P3 удерживает R3 и ждёт R1. Опишите, как обнаружить и разрешить ситуацию взаимной блокировки, предложите алгоритмы восстановления и обсудите их преимущества/недостатки
Кратко — как обнаружить и как восстановить. 1) Обнаружение - Для одноэкземплярных ресурсов (как в задаче): строят wait‑for‑graph, вершины — процессы, есть ребро Pi→PjP_i \to P_jPi→Pj если PiP_iPi ждёт ресурс, который удерживает PjP_jPj. Нахождение цикла в этом графе (DFS или поиск сильных компонент) указывает на взаимную блокировку. Сложность поиска цикла: O(n+e)O(n+e)O(n+e) (n — число процессов, e — число рёбер). Применение к примеру: ребра P1→P2P1 \to P2P1→P2, P2→P3P2 \to P3P2→P3, P3→P1P3 \to P1P3→P1 → цикл P1→P2→P3→P1P1 \to P2 \to P3 \to P1P1→P2→P3→P1 → deadlock. - Для многократных экземпляров ресурсов: используют алгоритм обнаружения взаимной блокировки, похожий на safety‑проверку Банковского алгоритма: - Пусть Work = Available, Finish[i]=false для всех процессов. - Найти процесс iii с Requesti≤WorkRequest_i \le WorkRequesti≤Work и Finish[i]=falseFinish[i]=falseFinish[i]=false; если найден — выполнить Work:=Work+AllocationiWork := Work + Allocation_iWork:=Work+Allocationi, Finish[i]:=trueFinish[i]:=trueFinish[i]:=true; повторять. - В конце все процессы с Finish[i]=falseFinish[i]=falseFinish[i]=false находятся в deadlock. Сложность примерно O(n⋅m)O(n \cdot m)O(n⋅m) (n — процессы, m — типы ресурсов) или O(n2)O(n^2)O(n2) в развертке. 2) Восстановление (алгоритмы и оценка) - Аборт всех процессов в цикле: - Плюсы: простое и гарантированно исправляет. - Минусы: высокий потерянный объём работы, возможны побочные эффекты на данные. - Поочерёдное прерывание (abort one by one) с выбором «жертвы» по эвристике (минимальная стоимость отмены, наименьший приоритет, наименьший удерживаемый ресурс и т.п.): - Плюсы: минимизирует общие потери, можно подобрать по политике. - Минусы: может потребоваться несколько итераций, сложность оценки стоимости. - Принудительное отнятие ресурсов (preemption) + откат/повторная попытка: - Плюсы: не нужно убивать процесс целиком, гибче. - Минусы: требуется поддержка отката (чекпойнты), может приводить к инверсии приоритетов и голоданию. - Откат процесса к контрольной точке (rollback): - Плюсы: меньше потерь, можно вернуть в консистентное состояние. - Минусы: нужен механизм чекпойнтов, накладные расходы на хранение состояний. - Изменение приоритета/реципиента ресурсов (preemption + приоритеты): - Плюсы: можно освободить ресурсы менее важными задачами. - Минусы: риск голодания низкоприоритетных задач, сложность выбора. - Комбинированные стратегии (панель: детектировать периодически, при deadlock — попытаться preempt/rollback для нескольких кандидатов, если не помогает — убивать): - Баланс между накладными расходами и потерями работы. 3) Практический пример восстановления в данной схеме - Самый простой метод: прервать один процесс из цикла, скажем P3P3P3. Тогда R3R3R3 освобождается → P2P2P2 получает R3R3R3, завершается и освобождает R2R2R2 → P1P1P1 получает R2R2R2 и завершается. Deadlock снят. - Альтернатива: выбрать жертву по минимальной стоимости (например процесс с наименьшим выполненным временем или наименьшим количеством удерживаемых ресурсов). Рекомендация: для систем с критичностью данных — предпочесть preemption/rollback с чекпойнтами; для простых систем с невысокой ценой прерывания — поочерёдный abort с выборе жертвы по эвристике. Для предотвращения — использовать стратегии избегания (например Banker's) если возможны прогнозируемые запросы.
1) Обнаружение
- Для одноэкземплярных ресурсов (как в задаче): строят wait‑for‑graph, вершины — процессы, есть ребро Pi→PjP_i \to P_jPi →Pj если PiP_iPi ждёт ресурс, который удерживает PjP_jPj . Нахождение цикла в этом графе (DFS или поиск сильных компонент) указывает на взаимную блокировку. Сложность поиска цикла: O(n+e)O(n+e)O(n+e) (n — число процессов, e — число рёбер).
Применение к примеру: ребра P1→P2P1 \to P2P1→P2, P2→P3P2 \to P3P2→P3, P3→P1P3 \to P1P3→P1 → цикл P1→P2→P3→P1P1 \to P2 \to P3 \to P1P1→P2→P3→P1 → deadlock.
- Для многократных экземпляров ресурсов: используют алгоритм обнаружения взаимной блокировки, похожий на safety‑проверку Банковского алгоритма:
- Пусть Work = Available, Finish[i]=false для всех процессов.
- Найти процесс iii с Requesti≤WorkRequest_i \le WorkRequesti ≤Work и Finish[i]=falseFinish[i]=falseFinish[i]=false; если найден — выполнить Work:=Work+AllocationiWork := Work + Allocation_iWork:=Work+Allocationi , Finish[i]:=trueFinish[i]:=trueFinish[i]:=true; повторять.
- В конце все процессы с Finish[i]=falseFinish[i]=falseFinish[i]=false находятся в deadlock.
Сложность примерно O(n⋅m)O(n \cdot m)O(n⋅m) (n — процессы, m — типы ресурсов) или O(n2)O(n^2)O(n2) в развертке.
2) Восстановление (алгоритмы и оценка)
- Аборт всех процессов в цикле:
- Плюсы: простое и гарантированно исправляет.
- Минусы: высокий потерянный объём работы, возможны побочные эффекты на данные.
- Поочерёдное прерывание (abort one by one) с выбором «жертвы» по эвристике (минимальная стоимость отмены, наименьший приоритет, наименьший удерживаемый ресурс и т.п.):
- Плюсы: минимизирует общие потери, можно подобрать по политике.
- Минусы: может потребоваться несколько итераций, сложность оценки стоимости.
- Принудительное отнятие ресурсов (preemption) + откат/повторная попытка:
- Плюсы: не нужно убивать процесс целиком, гибче.
- Минусы: требуется поддержка отката (чекпойнты), может приводить к инверсии приоритетов и голоданию.
- Откат процесса к контрольной точке (rollback):
- Плюсы: меньше потерь, можно вернуть в консистентное состояние.
- Минусы: нужен механизм чекпойнтов, накладные расходы на хранение состояний.
- Изменение приоритета/реципиента ресурсов (preemption + приоритеты):
- Плюсы: можно освободить ресурсы менее важными задачами.
- Минусы: риск голодания низкоприоритетных задач, сложность выбора.
- Комбинированные стратегии (панель: детектировать периодически, при deadlock — попытаться preempt/rollback для нескольких кандидатов, если не помогает — убивать):
- Баланс между накладными расходами и потерями работы.
3) Практический пример восстановления в данной схеме
- Самый простой метод: прервать один процесс из цикла, скажем P3P3P3. Тогда R3R3R3 освобождается → P2P2P2 получает R3R3R3, завершается и освобождает R2R2R2 → P1P1P1 получает R2R2R2 и завершается. Deadlock снят.
- Альтернатива: выбрать жертву по минимальной стоимости (например процесс с наименьшим выполненным временем или наименьшим количеством удерживаемых ресурсов).
Рекомендация: для систем с критичностью данных — предпочесть preemption/rollback с чекпойнтами; для простых систем с невысокой ценой прерывания — поочерёдный abort с выборе жертвы по эвристике. Для предотвращения — использовать стратегии избегания (например Banker's) если возможны прогнозируемые запросы.