19

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

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

但是,根据此处的文档,调用release()已释放的锁将引发异常:

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

有没有类似的查询功能aLock.isLocked()

4

1 回答 1

45

当然!

>>> 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退出,Python 会尽其所能释放锁)。

于 2013-10-19T00:19:49.967 回答