线程应用中的信号量同步失败,Python
我正在为一个数字泵制作一个图形界面应用程序,用来进行串行通信。不过,我在获取信息的更新机制上遇到了问题。update_values 方法每5秒会被一个QTimer(来自PySide模块)调用一次,但用户也可以通过调用同样的方法来手动请求更新。因此,我只希望有一个线程在执行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"
1 个回答
3
因为你在使用非阻塞的方式调用 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()
这个行为在文档中有描述:
acquire([blocking])
如果不带参数调用:当进入时,如果内部计数器大于零,就减一并立即返回。如果进入时计数器为零,就会阻塞,等待其他线程调用
release()
使计数器变大于零。这是通过适当的互锁机制完成的,因此如果多个acquire()
调用被阻塞,release()
会唤醒其中一个。具体唤醒哪个是随机的,所以被阻塞的线程被唤醒的顺序不能依赖。在这种情况下没有返回值。如果带上参数且设置为 true,执行的操作和不带参数时一样,并返回 true。
如果带上参数且设置为 false,则不会阻塞。如果不带参数的调用会阻塞,立即返回 false;否则,执行的操作和不带参数时一样,并返回 true。