syam syam - 22 days ago 8
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):
threading.Thread.__init__(self)
self.name=t
self.delay=d
self.array=arr;
self.lock=lock
def run(self):
self.fun1()


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

time.sleep(self.delay)

print "release lock for %s" %self.name
self.lock.release()
time.sleep(2)
print "lock status after lock release is",self.name,self.lock.locked()
lck=threading.Lock()
obj1=thread('T1',5,[1,2,3],lck)
obj2=thread('T2',10,[4,5,6],lck)


obj1.start()
obj2.start()


OUTPUT

=====
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

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()
True
>>> lck2.locked() # lck2 has been acquired as well as lck 
True
>>> lck2.release()
>>> lck.locked() # lck has been released as well as lck2
False

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.

Comments