在不同线程的类之间传递变量?

2024-09-24 22:20:53 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有两个类使用线程

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()

foo中的变量var1将随时间而变化,bar需要注意这些变化。这对我来说是有道理的,但我想知道这里是否有一些基本的东西最终会失败。这在python中是正确的吗?你知道吗


Tags: runnameselftruefooinitvaluedef
2条回答

尽管它效率很低,而且肯定不是最常见的使用文件传输数据的方法。一个线程将数据写入文件,例如作为json字符串,另一个线程读取数据。你知道吗

实际的共享部分与“如何与另一个对象共享一个值?”如果没有线程,所有相同的解决方案都可以工作。你知道吗

例如。您已经在将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,而不是子类或自定义映射类!)一直都是原子的,而且可能永远都是。如果你想依靠这个事实,你可以。但只有当锁被证明是一个重要的性能问题时,我才会这么做。我也会评论它的每一个用法,让它更清楚。你知道吗


如果您希望传递值而不是共享值,通常的答案是^{}或它的一个亲戚。你知道吗

但这需要重新设计你的程序。例如,您可能希望通过队列传递每个新的/更改的键值对。会是这样的:

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)

相关问题 更多 >