这段代码中真的需要互斥体吗?
Is a mutex really necessary in this piece of code?
下面的代码显示了我用于 PyQt 线程功能的 class。在我的主程序中,我实例化并启动了这个线程(即我使用 PyQt 的 moveToThread,countdown
是 运行 方法。)。当线程处于 运行ning 时,我经常调用 reset
方法。我不确定我实现的互斥量是否真的有必要,我希望有人能帮我解决这个问题。我执行了一个快速测试,其中我注释掉了互斥锁,这没有给我带来任何问题,即使我注释掉 time.sleep(1)
并在线程为 [=21] 时调用 reset
方法=]宁没有任何延迟。但是我不想 100% 安全,因此我在这里提出问题的原因。
import time
from PyQt4.QtCore import *
from threading import Lock
class Countdown(QObject):
finished = pyqtSignal()
def __init__(self, countdownInSec=30):
super(Countdown, self).__init__()
self.COUNTDOWN_IN_SEC = countdownInSec
self._countdownInSec = self.COUNTDOWN_IN_SEC
self._mutex = Lock()
@pyqtSlot()
def countdown(self):
while self._countdownInSec > 0:
print(self._countdownInSec)
self._mutex.acquire()
try:
self._countdownInSec -= 1
finally:
self._mutex.release()
time.sleep(1)
self.finished.emit()
def increment(self, seconds):
self._mutex.acquire()
try:
self._countdownInSec += seconds
finally:
self._mutex.release()
def reset(self):
self._mutex.acquire()
try:
self._countdownInSec = self.COUNTDOWN_IN_SEC
finally:
self._mutex.release()
提取主要内容(仅与本题相关的部分)
fpIntervUpdCountdownReset = pyqtSignal()
def __init__(self):
self.initFlightPathIntervUpdater()
def initFlightPathIntervUpdater(self):
self.fpIntervUpdCountdownThr = QThread()
self.fpIntervUpdCountdown = countdown.Countdown()
self.fpIntervUpdCountdown.moveToThread(self.fpIntervUpdCountdownThr)
self.fpIntervUpdCountdown.finished.connect(self.fpIntervUpdCountdownThr.quit)
self.fpIntervUpdCountdown.finished.connect(self.flightPathIntervUpdate)
self.fpIntervUpdCountdownThr.started.connect(self.fpIntervUpdCountdown.countdown)
def flightPathIntervUpdateReq(self):
if self.fpIntervUpdCountdownThr.isRunning():
self.fpIntervUpdCountdown.reset()
else:
print 'start'
self.fpIntervUpdCountdownThr.start()
@pyqtSlot()
def flightPathIntervUpdate(self):
print "perform flightPathIntervUpdate"
我会把它留在原处。
如果你不走运,你的 reset/increment 是由一个线程在 window 的一小段时间内执行的,就在倒计时线程读取计数器之后和写回其递减结果之前。然后它会覆盖更新的值,甚至看不到它。
那个时间 window 非常小,所以它可能不太可能发生,但有可能发生。
顺便提一下,使用锁的首选方式是:
def increment(self, seconds):
with self._mutex:
self._countdownInSec += seconds
下面的代码显示了我用于 PyQt 线程功能的 class。在我的主程序中,我实例化并启动了这个线程(即我使用 PyQt 的 moveToThread,countdown
是 运行 方法。)。当线程处于 运行ning 时,我经常调用 reset
方法。我不确定我实现的互斥量是否真的有必要,我希望有人能帮我解决这个问题。我执行了一个快速测试,其中我注释掉了互斥锁,这没有给我带来任何问题,即使我注释掉 time.sleep(1)
并在线程为 [=21] 时调用 reset
方法=]宁没有任何延迟。但是我不想 100% 安全,因此我在这里提出问题的原因。
import time
from PyQt4.QtCore import *
from threading import Lock
class Countdown(QObject):
finished = pyqtSignal()
def __init__(self, countdownInSec=30):
super(Countdown, self).__init__()
self.COUNTDOWN_IN_SEC = countdownInSec
self._countdownInSec = self.COUNTDOWN_IN_SEC
self._mutex = Lock()
@pyqtSlot()
def countdown(self):
while self._countdownInSec > 0:
print(self._countdownInSec)
self._mutex.acquire()
try:
self._countdownInSec -= 1
finally:
self._mutex.release()
time.sleep(1)
self.finished.emit()
def increment(self, seconds):
self._mutex.acquire()
try:
self._countdownInSec += seconds
finally:
self._mutex.release()
def reset(self):
self._mutex.acquire()
try:
self._countdownInSec = self.COUNTDOWN_IN_SEC
finally:
self._mutex.release()
提取主要内容(仅与本题相关的部分)
fpIntervUpdCountdownReset = pyqtSignal()
def __init__(self):
self.initFlightPathIntervUpdater()
def initFlightPathIntervUpdater(self):
self.fpIntervUpdCountdownThr = QThread()
self.fpIntervUpdCountdown = countdown.Countdown()
self.fpIntervUpdCountdown.moveToThread(self.fpIntervUpdCountdownThr)
self.fpIntervUpdCountdown.finished.connect(self.fpIntervUpdCountdownThr.quit)
self.fpIntervUpdCountdown.finished.connect(self.flightPathIntervUpdate)
self.fpIntervUpdCountdownThr.started.connect(self.fpIntervUpdCountdown.countdown)
def flightPathIntervUpdateReq(self):
if self.fpIntervUpdCountdownThr.isRunning():
self.fpIntervUpdCountdown.reset()
else:
print 'start'
self.fpIntervUpdCountdownThr.start()
@pyqtSlot()
def flightPathIntervUpdate(self):
print "perform flightPathIntervUpdate"
我会把它留在原处。
如果你不走运,你的 reset/increment 是由一个线程在 window 的一小段时间内执行的,就在倒计时线程读取计数器之后和写回其递减结果之前。然后它会覆盖更新的值,甚至看不到它。
那个时间 window 非常小,所以它可能不太可能发生,但有可能发生。
顺便提一下,使用锁的首选方式是:
def increment(self, seconds):
with self._mutex:
self._countdownInSec += seconds