Ответ
Взаимная блокировка (deadlock) возникает, когда два или более потока или процесса бесконечно ожидают ресурсы, которые заняты друг другом, создавая циклическую зависимость. Это приводит к остановке выполнения всех участвующих компонентов.
Для возникновения deadlock должны одновременно выполняться четыре условия Коффмана:
- Взаимное исключение (Mutual Exclusion): Ресурсы не могут быть разделены; только один процесс может использовать ресурс в данный момент.
- Удержание и ожидание (Hold and Wait): Процесс, уже владеющий одним или несколькими ресурсами, ожидает получения дополнительных ресурсов, занятых другими процессами.
- Отсутствие вытеснения (No Preemption): Ресурсы не могут быть принудительно отобраны у процесса, который ими владеет; они могут быть освобождены только добровольно.
- Циклическое ожидание (Circular Wait): Существует замкнутая цепочка процессов, где каждый процесс в цепочке ожидает ресурс, занятый следующим процессом в этой цепочке.
Пример на Python (потоки):
import threading
import time
# Два ресурса (блокировки), которые могут быть захвачены
lock1 = threading.Lock()
lock2 = threading.Lock()
def thread_func1():
print("Поток 1: Попытка захватить lock1...")
with lock1:
print("Поток 1: lock1 захвачен. Попытка захватить lock2...")
time.sleep(0.1) # Имитация работы
with lock2:
print("Поток 1: lock2 захвачен. Выполняю работу.")
print("Поток 1: Все блокировки освобождены.")
def thread_func2():
print("Поток 2: Попытка захватить lock2...")
with lock2:
print("Поток 2: lock2 захвачен. Попытка захватить lock1...")
time.sleep(0.1) # Имитация работы
with lock1:
print("Поток 2: lock1 захвачен. Выполняю работу.")
print("Поток 2: Все блокировки освобождены.")
t1 = threading.Thread(target=thread_func1)
t2 = threading.Thread(target=thread_func2)
t1.start()
t2.start()
t1.join()
t2.join()
print("Основной поток завершен.")
В этом примере, если t1 захватит lock1 и t2 захватит lock2 почти одновременно, то t1 будет ждать lock2 (который держит t2), а t2 будет ждать lock1 (который держит t1). Это создает циклическое ожидание, и оба потока заблокируются навсегда.
Предотвращение deadlock часто достигается путем нарушения одного или нескольких из этих четырех условий, например, путем упорядочивания захвата ресурсов или использования таймаутов.