线程应用程序的信号量同步失败



我正在构建一个GUI应用程序,用于与数字泵进行串行通信。我被用于从中获取信息的更新机制卡住了。update_values方法使用QTimer(来自PySide模块)每5秒调用一次,但用户可以通过调用相同的方法来特定地订购更新。出于这个原因,我只希望在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()

此行为在文档中有描述:

收购([阻塞])

当不带参数调用时:如果内部计数器大于输入为0,减1并立即返回。如果是的话进入时为0,阻塞,等待其他线程调用释放()使其大于零。这是用适当的方式完成的互锁,如果多个acquire()调用被阻塞,Release()将只唤醒其中一个。实现可能随机选择一个,因此被阻塞的线程被唤醒的顺序不应该依赖。在这种情况下没有返回值。

当block设置为true时,执行与true时相同的操作不带参数调用,返回true。

当阻塞设置为false时,不阻塞。如果一个电话没有参数会阻塞,立即返回false;否则,

返回true,与不带参数调用时相同。

最新更新