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