Query whether Python's threading.Lock is locked or not

25,779

Sure!

>>> from threading import Lock
>>> x = Lock()
>>> x.locked()
False
>>> x.acquire()
True
>>> x.locked()
True

You could also do a non-blocking acquire:

x.acquire(False)
x.release()

In this case, if x was unlocked then the code acquires it, and releases it. But if x was already locked, the non-blocking acquire returns at once (and returns False), and we again release it. But that's subject to races! There's nothing to stop some other thread from releasing the lock between those two lines.

Ditto for checking .locked(). That only tells you the state of the lock at the time .locked() was executed. It may no longer be true by the time you execute the next statement.

By the way, the body of run() is better written using the lock as a "context manager", like so:

def run(self):
    with aLock:
        self.clip = subprocess.call([ 'mplayer', 'Avatar.h264'], stdin=subprocess.PIPE)

This does the acquire()/release() pair for you, and is much more robust against unexpected exceptions raised in the body of the with block (Python does all it can to release the lock if the body is exited for any reason).

Share:
25,779

Related videos on Youtube

puk
Author by

puk

Updated on May 23, 2020

Comments

  • puk
    puk almost 4 years

    I have a thread I am running (code below) which launches a blocking subprocess. To ensure that other threads do not launch the same subprocess, I have a lock around this subprocess.call call. I also want to be able to terminate this subprocess call, so I have a stop function which I call from somewhere else. In the event that the subprocess is stopped prematurely, I want to release the lock as well, which is what the below code does:

    class SomeThread(threading.Thread):
       def run(self):
          aLock.acquire()
          self.clip = subprocess.call([ 'mplayer', 'Avatar.h264'], stdin=subprocess.PIPE)
          aLock.release()
       def stop(self):
          if self.clip != None and self.clip.poll() == True:
             try:
                self.clip.send_signal(signal.SIGINT)
             except:
                pass
          aLock.release()
    

    However, according to the documentation here, calling release() on a released lock will raise an Exception:

    A RuntimeError is raised if this method is called when the lock is unlocked.
    

    Is there a query function like aLock.isLocked()?

  • puk
    puk over 10 years
    It's like inception...we have to go deeper
  • ChickenFeet
    ChickenFeet almost 6 years
    Well why doesn't the documentation mention the locked() function?
  • porgull
    porgull over 4 years
    It does mention it in the docs, but it's easy to miss. It's at the bottom, in a different format than the rest of the functions: locked() Return true if the lock is acquired.