我有三个线程,两个用于读取串行接口,一个用于写入。两个读取线程的区别在于,一个管理一个优先的状态机,另一个收集测量数据并充当从机。伪代码看起来像这样...
class Test(object):
def __init__(self,stuff):
self._stuff = stuff
self.q = multiprocessing.Queue()
self.interface = serial.Serial(conn,baud)
self.data_event = threading.Event()
self.serial_lock = threading.Lock()
self.sync_time = 1
self.state = 'none'
self.new_state = 'none'
self.run()
def data_collect(self):
while True:
self.data_event.wait()
serial_output = self.interface.readline()
# ...
# data collection
# do stuff,put stuff in queue
# ...
time.sleep(self.sync_time)
def read_uart(self):
while True:
self.serial_lock.acquire()
serial_output = self.interface.readline()
# ...
# a bunch of logic to manage the state machine
# self.data_event.clear() in here somewhere
# do stuff,put stuff in queue
# ...
self.state = self.new_state
if(self.notify):
self.data_event.set()
self.serial_lock.release()
time.sleep(self.sync_time)
def measurement(self):
t = threading.Thread(target=self.read_uart)
t.setDaemon(True)
t.start()
t3 = threading.Thread(target=self.data_collect)
t3.setDaemon(True)
t3.start()
self.interface.write("<initial command>".encode())
while True:
self.serial_lock.acquire()
command = self.q.get() #other threads push commands to this queue
self.interface.write(command.encode())
self.serial_lock.release()
time.sleep(self.sync_time)
def run(self):
t2 = threading.Thread(target=self.measuerment)
t2.setDaemon(True)
t2.start()
我最初在 raspberry pi 3 A+ 上进行设置时遇到了麻烦,因为状态机会冻结或读取来自串行接口的乱码输出 - 但是当我将 self.sync_time 从 0.1 增加到 1 时,一切都开始正常安排并且按预期工作。
我现在试图让代码在稍有不同的硬件上运行,经过 10-20 次完美的工作状态机循环(有时小于 10 或大于 20),测量线程将在read_uart 之前的一行,导致状态机中断。顺序是这样的:
...
ACQUIRE UART
RELEASE UART
ACQUIRE MEASURE
RELEASE MEASURE
START DATA COLLECT
END DATA COLLECT
ACQUIRE MEASURE
RELEASE MEASURE
...
正常情况下,它看起来像:
...
ACQUIRE UART
RELEASE UART
ACQUIRE MEASURE
RELEASE MEASURE
START DATA COLLECT
END DATA COLLECT
ACQUIRE UART
RELEASE UART
...
我尝试用普通的 Lock() 和条件变量替换 threading.Event(),但每次都得到相同的结果。我什至看top,看看python是不是对硬件有负担,内存和cpu有充足的资源。
我更习惯于 C 中的多线程/多处理,所以我不确定我做错了什么......
如何强制我的线程每次都以正确的顺序执行? Measure线程怎么可能在read_uart之前抢锁两次?我是否造成了某种竞争条件?