查询Python的threading.Lock是否被锁定

时间:2013-10-19 00:10:46

标签: python multithreading thread-safety locking

我有一个正在运行的线程(下面的代码),它启动了一个阻塞子进程。为了确保其他线程不启动相同的子进程,我对此subprocess.call调用进行了锁定。我也希望能够终止这个子进程调用,所以我有一个stop函数,我从其他地方调用。如果子进程过早停止,我也想释放锁,这就是下面代码的作用:

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()

但是,根据文档here,在已发布的锁上调用release()会引发异常:

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

是否有像aLock.isLocked()这样的查询功能?

1 个答案:

答案 0 :(得分:30)

当然!

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

您还可以进行无阻塞获取:

x.acquire(False)
x.release()

在这种情况下,如果x已解锁,则代码会获取它并将其释放。但是如果x已被锁定,则非阻塞获取立即返回(并返回False),然后我们再次释放它。但那是受比赛影响的!没有什么可以阻止其他线程在这两行之间释放锁

同样检查.locked()。这只会告诉你.locked()执行时锁的状态。执行下一个语句时可能不再是真的。

顺便说一下,使用锁作为“上下文管理器”更好地编写run()的主体,如下所示:

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

这为你做了acquire()/release()对,并且对with块体中引发的意外异常更加健壮(如果正文退出,P​​ython会尽其所能释放锁定任何原因)。