syam syam - 11 months ago 43
Python Question

.locked() returns True even after release() called in python multithreading environment

I was trying to write my first code using python thread.

Please see the code
There is an issue when i release lock for a thread using release() as it says the lock is still availabe [locked() returns True even after release()]

import threading
import time

class thread (threading.Thread):
def __init__(self,t,d,arr,lock):
def run(self):

def fun1(self):
print "the thread %s want to take a lock now"
print "lock status just after lock acquire foe",,self.lock.locked()


print "release lock for %s"
print "lock status after lock release is",,self.lock.locked()



the thread T1 want to take a lock now
the thread T2 want to take a lock now

lock status just after lock acquire foe T2 True
release lock for T2
lock status just after lock acquire foe T1 True
lock status after lock release is T2 True
release lock for T1
lock status after lock release is T1 False

What my problem is:

Thread T2 got the lock first and it executed its space.
We can see lock status for T2 using .locked() is "lock status just after

lock acquire foe T2 True". So T2 got lock now.
Once T2 released the lock using release(), then T1 acquired the lock also as expected

But after lock release for T2 using release(), the locked() says True. This means still lock available for T2? In this case how T1 acquired lock?. Once the T1 executed and after release(), I can see .locked() returns False. means for T1 the locked() worked as expected as once it releases lock, immediatly it return False

So in a nutshell,
Why my first thread T2 returned True even after its lock release?
If I execute only 1 thread it works as expected.

Answer Source

When you pass a lock object to the constructor, it isn't getting copied, so each thread object has access to the very same lock.

This results in self.lock.locked() returning True because the lock is still locked, but this time it has been locked by another thread.

This is what actually happens:

>>> import threading
>>> lck = threading.Lock() # the 'original'
>>> lck2 = lck # lck2 isn't a copy of lck!
>>> lck.acquire()
>>> lck2.locked() # lck2 has been acquired as well as lck 
>>> lck2.release()
>>> lck.locked() # lck has been released as well as lck2

Again, this happens because lock objects aren't (and cannot be) copied around and whatever variable is assigned to some lock, it will point to the original object.