I wrote a really simple code in order to mimic a condition that I encountered recently. But I could not quite understand why does this happen exactly. Could anyone explain in detail the reason for an infinite loop because of the usage of locks.
Test Code (that mimics the condition)
import threading
# Declare Lock
jobs_lock = threading.Lock()
while True:
# Acquire the Lock
jobs_lock.acquire()
print("Lock Acquired")
if 1:
continue
else:
print("useless else")
jobs_lock.release()
Output
Lock Acquired
<cursor-blinking>
A naive way which I could think of was to release lock after each continue that I used in the original piece of code. Which looks something like this.
import threading
# Declare Lock
jobs_lock = threading.Lock()
while True:
# Acquire the Lock
jobs_lock.acquire()
print("Lock Acquired")
if 1:
jobs_lock.release()
continue
else:
print("useless else")
jobs_lock.release()
Could anyone explain why exactly is this nature acquired ? Should the thread not know that it has the control of the lock and should proceed to execute the code ?
When you use continue
, further processing of the loop body is skipped and the control moves back to the top of the loop, i.e. to the loop condition (in your case it is while True:
).
Once the loop body begins execution again, it tries to acquire a lock that had already been acquired in the previous iteration of the loop. Hence your thread will block forever as the lock will never be released, as in the given example we'll never reach the section of the loop that releases the lock. This will cause a deadlock condition, resulting in your code's execution to suspend.
It's worth noting that threads are not smart enough to realise that they are acquiring a lock that they have already acquired sometime earlier, though a wrapper could be written and used to keep a map of the locks and the threads that have acquired them to prevent such conditions.
Your second solution does solve the deadlock problem, correctly.