我有以下代码:
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
Run Code Online (Sandbox Code Playgroud)
现在,如果抛出异常,锁似乎不会被删除,导致互斥锁未被释放.我可以在任何地方做"del lock",但这会消除qmutexlocker的全部意义.这与Python垃圾收集有关吗?如果是这样,那必然意味着QMutexLocker在Python中根本不可用?
jdi*_*jdi 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
Run Code Online (Sandbox Code Playgroud)
在测试中,您在第一个示例中看到,锁定返回仍然处于锁定状态.在第二种情况下,当引发异常时,上下文管理器在离开函数之前释放锁.
在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
Run Code Online (Sandbox Code Playgroud)
如果您希望在引发异常之前释放互斥体,请释放它:
\n\ndef query(self, query):\n lock = QMutexLocker(self.mutex)\n reply = self.conn.query(query)\n if re.search("error", reply):\n lock.unlock()\n raise GeneralError("Query error")\n
Run Code Online (Sandbox Code Playgroud)\n\n如果你希望当lock
它超出范围时立即被释放,那么你对解释器的期望太高了。既然您确切地知道何时以及为何应该释放锁,那就这么做吧。
作为一般规则 \xe2\x80\x94 Python 或其他地方 \xe2\x80\x94 你应该始终有一个互斥体绑定尽可能小的操作。我假设您知道无论查询正在做什么实际上都需要保护,并且在调用self.conn.query
.
添加回应评论:
\n\n这是一个公平的观点,“一定意味着 QMutexLocker 根本不可用”,我确实错过了。我假设您指的是PySide.QtCore.QMutexLocker,它提出了不太可能的声明:
\n\n\n\n\n现在,当 PySide.QtCore.QMutexLocker 对象被销毁时(当函数返回时,因为 locker 是一个自动变量),互斥锁将始终被解锁。
\n
这不太可能,因为Python中没有auto
变量存储类这样的东西。我怀疑,经过进一步调查,这将被证明是“让我们包装一个 C++ 库并假设作用域语义起作用”。如果这个猜测是正确的,您可以使用with 语句来更好地保证可靠的解锁。
归档时间: |
|
查看次数: |
1277 次 |
最近记录: |