Вопрос проверяет понимание рекурсивных блокировок и умение предотвращать deadlock в более сложной логике потоков.
RLock используют, когда один и тот же поток может повторно захватывать блокировку. Это часто происходит при вложенных вызовах функций или рекурсии. Обычный Lock в таких случаях приведёт к deadlock. RLock отслеживает, сколько раз поток захватил блокировку. Это делает код безопаснее, но чуть менее производительным.
На практике блокировки редко используются в изолированных функциях. Чаще одна защищённая функция вызывает другую, которая тоже работает с общими данными.
Определение:
Deadlock — это ситуация, когда поток навсегда ждёт освобождения ресурса, который он сам удерживает.
Пример проблемы:
from threading import Lock
lock = Lock()
def outer():
with lock:
inner()
def inner():
with lock: # deadlock
pass
Здесь один и тот же поток пытается захватить Lock повторно и зависает.
RLock запоминает:
Какой поток владеет блокировкой
Сколько раз она была захвачена
Пример:
from threading import RLock
lock = RLock()
def outer():
with lock:
inner()
def inner():
with lock:
pass
Рекурсивные функции
Вложенные методы одного класса
Переиспользуемые функции с общей блокировкой
Сложная бизнес-логика с цепочкой вызовов
Медленнее Lock
Легче скрыть ошибки проектирования
Вывод:
Используй RLock, когда невозможно гарантировать, что блокировка будет захвачена только один раз в одном потоке.