2015-05-08 91 views
1

下面的代碼顯示了一個我用於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" 

回答

1

我會離開它在哪裏。
如果你倒黴,你的重置/增量是在倒計時線程讀取計數器之後,在寫入其遞減結果之前的一個小時間窗口中由一個線程執行的。然後它會覆蓋更新後的值而不會看到它。
時間窗口非常小,所以它可能不太可能發生,但這是可能的。

順便說來使用鎖的優選方式是:

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