假设我有两个使用线程的类
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
def run(self):
while True
value, name = getvalue() // name is an string
self.var1[name] = value
bar(self)
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
def run(self):
while True
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
f = foo()
f.start()
var1
中的变量foo
会随着时间的推移而发生变化,bar
需要了解这些变化。这对我来说很有意义,但我想知道这里有什么根本可能最终失败的东西。这在python中是正确的吗?
答案 0 :(得分:0)
实际的共享部分与“我如何与另一个对象共享一个值?”的问题相同。没有线程,所有相同的解决方案都可以工作。
例如。您已将foo
实例传递到bar
初始化程序,因此只需从那里获取:
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
但这是线程安全吗?
嗯,是的,但只是因为你从未真正开始后台线程。但我假设在您的实际代码中,您将同时运行两个线程,两者都访问var1
值。在这种情况下,如果没有某种同步,它就不是线程安全的。例如:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.var1lock = threading.Lock()
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
self.var1lock = fooInstance.var1lock
现在,而不是这个:
self.var1[name] = value
...你这样做:
with self.var1lock:
self.var1[name] = value
同样,而不是:
val = myOtherfunction(fooInstance.var1[arg]) //other function
...你这样做:
with self.var1lock:
var1arg = var1[arg]
val = myOtherfunction(var1arg)
或者......事实证明,在CPython中,更新dict中的单个键的值(只有内置dict
,而不是子类或自定义映射类!)一直是原子的,可能总是将会。如果你想依靠这个事实,你可以。但是,如果锁定是一个重要的性能问题,我只会这样做。我也会评论它的每一个用途,以表明它。
如果你宁愿传递值而非分享,那么通常的答案是queue.Queue
或其中一位亲戚。
但这需要重新设计你的程序。例如,您可能希望在队列中传递每个新的/更改的键值对。这将是这样的:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.q = queue.Queue()
def run(self):
b = bar(self)
b.start()
while True:
value, name = getvalue() // name is an string
self.var1[name] = value
self.q.put((name, value))
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = copy.deepcopy(fooInstance.var1)
self.q = fooInstance.q
def _checkq(self):
while True:
try:
key, val = self.q.get_nowait()
except queue.Empty:
break
else:
self.var1[key] = val
def run(self):
while True:
self._checkq()
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
答案 1 :(得分:-1)
虽然效率非常低,当然也不是最常用的方法,您可以使用文件传输数据。一个线程将数据写入文件,例如作为json字符串,另一个线程读取它。