5

我有以下代码:

def query(self,query):
  lock = QMutexLocker(self.mutex)
  reply = self.conn.query(query)
  if (re.search("error", reply) != None):
    raise GeneralError("Query error")

  #more code...  
  return reply

现在,如果抛出异常,锁似乎没有被删除,导致互斥锁没有被释放。我当然可以到处做“del lock”,但这会带走 qmutexlocker 的全部意义。这与 Python 垃圾收集有关吗?如果是这样,那一定意味着 QMutexLocker 在 Python 中根本不可用?

4

2 回答 2

12

您没有正确使用 QMutexLocker。像上下文管理器一样使用它:

from PyQt4.QtCore import QMutex, QMutexLocker

def bad_lock(aLock):
    locker = QMutexLocker(aLock)
    print "Locked"
    raise RuntimeError("Test exception")

    return "Should not get here"

def good_lock(aLock):
    with QMutexLocker(aLock):
        print "Locked"
        raise RuntimeError("Test exception")

    return "Should not get here"

lock = QMutex()

bad_lock(lock)
print lock.tryLock()
# False

lock.unlock()

good_lock(lock)
print lock.tryLock()
# True

在测试中,您在第一个示例中看到,锁返回仍处于锁定状态。第二,当引发异常时,上下文管理器在离开函数之前释放锁。

当在 C++ 中使用时,我确信 QMutexLocker 会做它应该做的事情,只要作用域结束就会解锁。但是在 Python 中,正如您所发现的,不应该依赖垃圾收集器来进行解锁。通过语句的上下文管理器with非常适合这一点。您可以通过此类的 C++ 示例显示它只是在函数顶部创建它的方式来判断。而 python 版本同时具有 an__enter____exit__方法。

最后,with上下文允许您将关键代码块包装在锁中以限制需要到位的锁的数量,因此您可以执行以下操作:

def good_lock(aLock):

    # do a bunch of stuff here
    ...

    # critical section
    with QMutexLocker(aLock):
        # do critical stuff here
        ...

    # do other stuff here
    ...

    return True
于 2012-06-30T03:35:28.190 回答
0

如果您希望在引发异常之前释放互斥锁,请释放它:

def query(self, query):
    lock = QMutexLocker(self.mutex)
    reply = self.conn.query(query)
    if re.search("error", reply):
        lock.unlock()
        raise GeneralError("Query error")

如果您希望在lock超出范围时立即释放它,那么您对解释器的期望过高。既然您确切地知道何时以及为什么应该释放锁,那就去做吧。

作为一般规则 - Python 或其他地方 - 您应该始终将互斥锁绑定到尽可能小的操作。我假设您知道任何查询实际上都需要保护,并且在调用self.conn.query.

添加以回应评论

这是一个公平的观点,“一定意味着 QMutexLocker 根本不可用”,我确实错过了。我假设您指的是PySide.QtCore.QMutexLocker这不太可能声称:

现在,当 PySide.QtCore.QMutexLocker 对象被销毁时,互斥锁总是会被解锁(当函数返回时,因为 locker 是一个自动变量)。

这不太可能,因为autoPython 中没有变量存储类之类的东西。我怀疑这将在进一步调查后证明是“让我们包装一个 C++ 库并假设范围语义工作”。如果这个猜测是正确的,你可能会使用with 语句来更好地保证可靠的解锁。

于 2012-06-29T12:48:15.647 回答