I have a threading.Lock
object and I would like to know if the current_thread
is holding this lock. What would be the simplest way of achieving this?
-
1What are you trying to accomplish? You might want to use a [reentrant lock](https://docs.python.org/2/library/threading.html#threading.RLock). See http://stackoverflow.com/questions/22885775/python-reentrant-lock-differences-with-lock for a little bit more on them. – Rob Watts May 13 '14 at 15:49
-
If it's for debugging, it's also possible to wrap the `Lock` object to keep the information. See [multithreading - Is it possible to subclass Lock() objects in Python? If not, other ways to debug deadlock? - Stack Overflow](https://stackoverflow.com/questions/6780613/is-it-possible-to-subclass-lock-objects-in-python-if-not-other-ways-to-debug?noredirect=1&lq=1) – user202729 Aug 23 '21 at 13:23
4 Answers
There is no direct way to do this with threading.Lock
objects that I know of. Those do have a locked
attribute, but that will show up as True
in all threads, not just the owning thread. It's possible with RLock
, but you have to access an internal __owner
attribute on the RLock object, which isn't advisable or guaranteed to always work. The code to do is would look like this, for what its worth:
#!/usr/bin/python
import threading
import time
def worker():
if l._RLock__owner is threading.current_thread():
print "I own the lock"
else:
print "I don't own the lock"
l.acquire()
if l._RLock__owner is threading.current_thread():
print "Now I own the lock"
else:
print "Now I don't own the lock"
time.sleep(5)
l.release()
if __name__ == "__main__":
l = threading.RLock()
thds = []
for i in range(0, 2):
thds.append(threading.Thread(target=worker))
thds[i].start()
for t in thds:
t.join()
Here's the output:
dan@dantop:~> ./test.py
I don't own the lock
Now I own the lock
I don't own the lock
But in reality, your code really shouldn't need to do this. Why do you feel like you need this explicit check? Typically when you're writing a block of code, you know whether or not a lock has been acquired in that context. Can you share an example where you think you need to check it?

- 91,354
- 19
- 222
- 219
-
**Note**: the method mentioned above with `RLock` does not work in Python 3 (in fact because it uses an undocumented feature, it may break in any new version). – user202729 Aug 23 '21 at 13:31
The help text for the release
method:
Help on built-in function release:
release(...)
release()
Release the lock, allowing another thread that is blocked waiting for
the lock to acquire the lock. The lock must be in the locked state,
but it needn't be locked by the same thread that unlocks it.
This implies that Lock
objects don't care who locked them, as any thread can unlock them. So with unmodified lock objects, there is no way to determine if the current thread is the one holding the lock because no thread "holds" the lock - it is simply either locked or unlocked.
I assume that the reason you would want to know if you are holding the lock or not is so that you don't try to acquire the lock when you already have it. For example:
def a():
with theLock:
do_stuff()
b()
do_other_stuff()
def b():
with theLock:
do_b_stuff()
Here, you only want to acquire theLock
in b()
if the thread does not already have the lock. This, as I mentioned in my comment, is a perfect use case for a reentrant lock. If you create the lock like this:
theLock = threading.RLock()
Then the example I presented works just fine - when you call a()
, it acquires the lock. Then in b()
, it lets you reacquire the lock without complaining. Additionally, if you are using the context manager syntax (with theLock:
) you won't need to worry about the one caveat.
The caveat is that if you are manually calling acquire
and release
, then you need to make sure that you call release
once for every time you call acquire
. In my above example, if I had called theLock.acquire()
in both a()
and b()
, I would have needed to call release()
in both functions as well. If you call acquire
twice and release
only once, then the lock will still be held by that thread, making other threads unable to acquire the lock.

- 6,866
- 3
- 39
- 58
-
A good reason for checking this is for functions to assert that their caller has acquired a lock before calling. – Brent Sep 07 '20 at 16:47
Please take a look at Thread Synchronization Mechanisms
You could try the following
import threading
lock = threading.Lock()
lock.acquire()
#now that the lock is taken, using lock.acquire(False) will return False
if not lock.acquire(False):
# could not lock the resource
Now adding a twist to this:
import threading
class customLock(object):
_accessLock = threading.Lock()
def __init__(self):
self._lock = threading.Lock()
self.ownerThread = None
def acquire(self, thread):
self._accessLock.acquire()
try:
if self._lock.acquire():
self.ownerThread = thread
finally:
self._accessLock.release()
def release(self):
self._accessLock.acquire()
try:
self._lock.release()
self.ownerThread = None
finally:
self._accessLock.release()
def getOwner(self):
return self.ownerThread
def acquire(self, blocking=True):
return self._lock.acquire(blocking)
Turning the initial example into:
import threading
lock = customLock()
lock.acquire(threading.current_thread())
#now that the lock is taken, using lock.acquire(False) will return False
if not lock.acquire(False):
# could not lock the resource
if lock.getOwner() is threading.current_thread():
# do something
Hope this helps

- 1
- 2
-
1Hi drapal, I like this approach, the only concern I have here is that def release(self): step - 1 self._lock.release() step - 2 self.ownerThread = None the steps 1 and 2 are not atomic, wouldn't this lead to the owerThread being None even when someone has acquired the lock ? – Rahul May 13 '14 at 17:16
-
In Python 3.9.5, to get the owner thread of a RLock
object:
For debugging purpose: You can simply print the lock out, and the output would be something like
<unlocked _thread.RLock object owner=0 count=0 at 0x7f77467d1030>
Look at the
owner
property, which contains the thread ID of the owner thread.To get the value of the owner programmatically: (warning: uses implementation details, might break in future versions;; also note that there may be a race condition between when you check the owner and actually use the information)
It depends on whether Python is using the Python implementation, or the C implementation.
In [12]: threading._CRLock() # this is a recursive lock implemented in C Out[12]: <unlocked _thread.RLock object owner=0 count=0 at 0x7f7746878cc0> In [13]: threading._PyRLock() # this is a recursive lock implemented in Python Out[13]: <unlocked threading._RLock object owner=None count=0 at 0x7f7746764cd0>
The following method only works if the implementation is in Python.
Just access the
_owner
attribute:threading._PyRLock()._owner

- 3,358
- 3
- 25
- 36