【问题标题】:Is a mutex really necessary in this piece of code?在这段代码中真的需要互斥锁吗?
【发布时间】:2015-07-19 10:58:50
【问题描述】:

下面的代码显示了一个用于 PyQt 线程功能的类。在我的主程序中,我实例化并启动这个线程(即我使用 PyQt 的 moveToThread,countdown 是运行方法。)。在线程运行时,我经常调用reset 方法。我不确定我实现的互斥锁是否真的有必要,我希望有人可以为我解决这个问题。我已经执行了一个快速测试,其中我已经注释掉了互斥锁,这没有给我带来任何问题,即使我注释掉 time.sleep(1) 并在线程运行时调用 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"

【问题讨论】:

    标签: python pyqt mutex


    【解决方案1】:

    我会把它留在原处。
    如果您不走运,则您的重置/增量是由一个线程在倒计时线程读取计数器之后和写回其减量结果之前由一个线程在小时间窗口中执行的。然后它会覆盖更新的值,甚至看不到它。
    那个时间窗口非常小,所以它可能不太可能发生,但有可能。

    顺便说一句,使用锁的首选方式是:

    def increment(self, seconds):
        with self._mutex:
            self._countdownInSec += seconds
    

    【讨论】:

      猜你喜欢
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 2010-09-12
      • 2013-01-01
      相关资源
      最近更新 更多