A reentrant lock lets the same thread acquire a lock repeatedly, including while recursively re-entering a critical section. Each acquisition requires a matching release; an internal recursion count releases the lock for other threads only when it reaches zero. Python provides this behavior through threading.RLock. section 7.3.1
Recursive list summation
A recursive sum_list function acquires a normal Lock, processes one list element, and calls itself for the remainder. The second acquisition blocks the same thread forever. Replacing Lock with RLock allows the recursion to continue, provided every acquisition is eventually released. section 7.3.1
Use reentrant locks to address self-reentry, but keep their limits in mind:
- They prevent a thread from deadlocking itself when recursion or nested method calls reacquire the same lock. section 7.3.1
- They do not resolve deadlocks between threads that hold different locks and wait for one another. section 7.3.2
- They require balanced acquisition and release so the recursion count can return to zero. section 7.3.1
Listing 7.9 Recursion with locks
from threading import Lock, Thread
from typing import List
list_lock = Lock()
def sum_list(int_list: List[int]) -> int:
print('Waiting to acquire lock...')
with list_lock:
print('Acquired lock.')
if len(int_list) == 0:
print('Finished summing.')
return 0
else:
head, *tail = int_list
print('Summing rest of list.')
return head + sum_list(tail)
thread = Thread(target=sum_list, args=([1, 2, 3, 4],))
thread.start()
thread.join()
Trace the recursive lock acquisition that hangs with Lock before comparing it with the RLock replacement. section 7.3.1

