我正在构建用于与数字泵进行串行通信的GUI应用程序。我陷入了用于从中获取信息的更新机制中。使用QTimer(来自PySide模块)每5秒钟调用一次update_values方法,但是用户可以通过调用相同的方法来专门订购更新。因此,我只希望一个线程在update_values代码上运行。但是,使用一个信号量或一个锁似乎不起作用,因为有多个线程随意进入该信号量块:

self.update_sema = threading.Semaphore(value=1)


...
...

def update_values(self, initialize = False):
    """This is the parameters update method."""

    self.update_sema.acquire(False)
    print "ENTERED THE SEMAPHORE"
    self.update_thread = threading.Thread(\
            target = self.actual_update_method,\
            args = (initialize,))
    self.update_thread.start()
def actual_update_method(self, initialize):

    # reading info mechanism
    self.status["absolute_pos"] = self.send_Command('?', 10)[3:]
    self.status["actual_pos"] = self.send_Command('?4', 10)[3:]
    self.status["starting_vel"] = self.send_Command('?1', 10)[3:]
    self.status["top_vel"] = self.send_Command('?2', 10)[3:]
    self.status["cutoff_vel"] = self.send_Command('?3', 10)[3:]
    self.status["backlash_steps"] = self.send_Command('?12', 10)[3:]
    self.status["fluid_sensor"] = self.send_Command('?22', 10)[3:]
    self.status["buffer_status"] = self.send_Command('?F', 10)[3:]

    # These must be asked only once, at the initialization phase
    if initialize:
        #print "version set as well!"
        self.status["version"] = self.send_Command('?&', 10)[3:]
        self.status["checksum"] = self.send_Command('?#', 10)[3:]

    self.update_sema.release()
    print "EXITED THE SEMAPHORE"

最佳答案

因为您正在使用对acquire的非阻塞调用(通过使用acquire(blocking=False)),所以需要确保仅在实际获得信号量的情况下才继续使用该方法,如下所示:

def update_values(self, initialize = False):
    """This is the parameters update method."""

    if self.update_sema.acquire(False):
        print "ENTERED THE SEMAPHORE"
        self.update_thread = threading.Thread(\
                target = self.actual_update_method,\
                args = (initialize,))
        self.update_thread.start()


documentation中描述了此行为:


  获取([阻止])
  
  不带参数调用时:如果内部计数器大于
  进入时为零,递减一并立即返回。如果是
  进入时为零,阻塞,等待其他线程调用
  release()使其大于零。这是通过适当的方式完成的
  互锁,以便在阻止多个generate()调用时,
  release()会唤醒其中之一。实施可能
  随机选择一个,这样唤醒被阻塞线程的顺序
  不应该依赖。在这种情况下,没有返回值。
  
  在将blocking设置为true的情况下调用时,请执行与when相同的操作
  调用时不带参数,并返回true。
  
  在将阻塞设置为false的情况下调用时,请勿阻塞。如果有电话
  没有参数将阻塞,立即返回false;除此以外,
  执行与不带参数调用时相同的操作,并返回true。

关于python - 线程应用程序的信号量同步失败,Python,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24150271/

10-09 17:15
查看更多