【问题标题】:Sharing objects between threads in Python在 Python 中的线程之间共享对象
【发布时间】:2021-03-05 17:38:31
【问题描述】:

我在 Python 中使用线程时遇到了一些问题。

我需要的是:

线程 1

  • 启动线程 2,给它 'data' 对象作为参数
  • 做一些工作
  • 停止线程 2
  • 检查结果

线程 2

  • 在循环中读取线程 1 的数据

我大致实现为

class ReaderThread(threading.Thread)
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.exit = False

    def run(self):
        while not self.exit:
            somehow modify self.data

    def stop(self):
        self.exit = True
        self.join()

主线程创建一个 ReaderThread 实例并调用 start(),几秒钟后它调用 stop()。

class MainThread():
    def __init__(self):
        self.data = set()
        self.thread = ReaderThread(self.data)

    def function(self):
        self.thread.start()
        whoptydoo
        self.thread.stop()

问题是,thread1 并没有真正修改 thread2 的“exit”变量,而 thread2(ReaderThread)也没有修改 thread1 的“data”。所以这里显然存在一些内存共享问题。

我的想法是“它只是所有指针”,这似乎不正确。 请问这样做的正确方法是什么?

【问题讨论】:

  • 我想你创建了两个ReaderThread 实例然后运行它们。好吧,self 指的是实例,每个实例都有自己的状态。因此,很明显,thread1 和 thread2 将有自己的值 exit,而不是共享同一个值。
  • @go2nirvana ReaderThread只有一个,我加了一些代码
  • 那么您在问题中所说的第二个线程是什么?
  • Thread1 = 主线程,Thread2 = ReaderThread
  • This answer 似乎可以解决您的问题。要么接受它,要么关闭这个问题,因为您的错误似乎是由拼写错误引起的。

标签: python multithreading


【解决方案1】:

这里是交易:你有data 字段ReaderThreaddata 字段MainThread。当您在ReaderThread 中执行此self.data = smth 时,您为ReaderThread 字段设置此值,但您永远不会访问MainThread 的任何属性。两个实例都有类似名称的字段,但它们并不相同。

要实现您想要的,您应该从ReaderThread.run 返回一个值,或者将MainThread 实例传递给ReaderThread 以便能够对其进行修改。看起来选项 2 更适合您。

class ReaderThread(threading.Thread)
    def __init__(self, main_instance):
        self.main = main_instance
        self.exit = False

    def run(self):
        while not self.exit:
            self.main.data = whatever

    def stop(self):
        self.exit = True
        self.join()

class MainThread():
    def __init__(self):
        self.data = set()
        self.thread = ReaderThread(self)

    def function(self):
        self.thread.start()
        whoptydoo
        self.thread.stop()

附:仔细观察后,我对你做错了什么有了另一个想法。由于MainThread.dataset(),因此是可变的 - 您的代码将按原样工作,但前提是您完全修改 data,但不重新分配它(我怀疑,您可以完成)。

【讨论】:

  • 我只使用 data.add()/data.remove()。我会尝试传递 MainThread 的实例。
  • 嗯..不,似乎没有帮助:(但是让我们把 self.data 放在一边。我认为调用 stop 函数也不会改变读者的 self.exit线程,我已经在使用整个线程的实例。对 self.join() 的调用只是挂起..可以理解..
  • @Pyjong 你用的是什么版本的 Python? CPython?杰通?在哪个平台上?
  • 3.9.在 Windows 上
【解决方案2】:

您的RenderThread 类似乎不完整(缺少:Thread 初始化)。 完成后,您的示例似乎按预期工作。

EDIT在问题中的示例更改后,它仍然有效...

#!/usr/bin/env python

import time
import threading

class ReaderThread(threading.Thread):
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.exit = False

    def run(self):
        t0=time.time()
        while not self.exit:
            # somehow modify self.data
            time.sleep(0.25)
            self.data.add(int(100.0*(time.time()-t0)))

    def stop(self):
        self.exit = True
        self.join()

class MainThread():
    def __init__(self):
        self.data = set()
        self.thread = ReaderThread(self.data)

    def function(self):
        self.thread.start()
        time.sleep(2) # whoptydoo
        self.thread.stop()

mt=MainThread()
mt.function()
print(mt.data) # {225, 100, 200, 75, 175, 50, 150, 25, 125}

【讨论】:

  • 啊.. 对不起,我实际上是在我的代码中调用 super().__init__() 我只是忘了在这里输入它。 super() 的参数重要吗? (ReaderThread 不直接继承其他任何东西)
  • @Pyjong 对于您的用例,默认的Thread constructor 就可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多