我有一个硬件传感器。我需要不断读取传感器并对之前3秒的读数进行一些数学计算。 (我读的越快,我的样本越多,我的结果就越好,所以我想不断调用我的函数。)我需要在请求时向用户(通过Web调用)提供当前结果。结果可能会在亚秒级基础上发生显着变化。用户可以尽可能快地或非常不频繁地请求更新。
我目前有以下代码,可以使用。
from threading import Thread
from MySensorReadAndMath import MySensorReadAndMath
class ManageSensor(Thread):
def __init__(self):
Thread.__init__(self)
self.result={}
self.mySensorReadAndMath = MySensorReadAndMath()
def updateResult(self):
result = {}
result['value1'] = self.mySensorReadAndMath.value1
result['value2'] = self.mySensorReadAndMath.value2
return result
def getResult(self):
return self.result
def run(self):
while True:
self.mySensorReadAndMath.update()
self.result = self.updateResult()
在另一段代码中,我创建了类,使用Flask创建对 ManageSensor.getResult()的Web调用以返回结果,并启动该线程。
这是线程安全的吗? (我可以获取当前的 value1 和之前的 value2 ,还是损坏的 self.result ?)如果它不是线程安全的,那么会怎样?我没有阻止它使它成为线程安全的吗?
我考虑的具体事项:
答案 0 :(得分:1)
通常我会尝试使用内置的Queue类,但这种情况可能太复杂了。
如果我理解正确,无论用户提出多少请求,您都需要存储三秒钟的数据。您可以通过利用Python始终通过引用访问对象的事实来解决此问题。分配引用是Python中的原子操作,因此您可以安全地使用单例来存储最新结果。有两个条件:
因此,使用单例来强制执行此行为:
class Buffer:
''' A simple buffer that stores exactly one value '''
latest = None
@staticmethod
def onNewReading(*args, **kwds): # or any parameters one fancies
# Pack the results in a single object and store it
Result.latest = (args, kwds)
@staticmethod
def onUserRequest():
return Result.latest
写一个值如下:
def process():
# Do the measurement
# Do the calculation
Buffer.onNewReading(data1, data2, etc)
使用值:
def handleRequest():
results = Buffer.onUserRequest()
# Format a response, using the results
if not results:
return 'No data available' # or any other useful error message
return response(results[0][0], results[0][1])
答案 1 :(得分:0)
这不是线程安全的。
客户端线程可以在updateResult运行时调用getResult,因此结果可能为空,半满或包含旧值。
制作另一个对象并在之后将其分配给结果将限制半填充数据的可能性,因此这是一个加号。
队列解决方案还需要某种锁定