在Python3.6中,我使用threading.local((来存储线程的一些状态。这里有一个简单的例子来解释我的问题:
import threading
class Test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.local = threading.local()
self.local.test = 123
def run(self):
print(self.local.test)
当我启动此线程时:
t = Test()
t.start()
Python给了我一个错误:
AttributeError: '_thread._local' object has no attribute 'test'
似乎测试属性无法访问__init__函数范围之外,因为我可以在本地设置属性 test=123 后打印__init__函数中的值。
是否有必要在 Thread 子类中使用 threading.local 对象?我认为线程实例的实例属性可以保持属性线程安全。
无论如何,为什么 threading.local 对象在实例函数之间没有按预期工作?
当你构建你的线程时,你使用的是不同的线程。 在线程上执行 run 方法时,将启动一个新线程。 该线程尚未设置线程局部变量。 这就是为什么您没有在构造线程对象的线程上设置的属性,而不是在运行该对象的线程上设置的属性。
如 https://docs.python.org/3.6/library/threading.html#thread-local-data 所述:
对于不同的线程,实例的值将有所不同。
Test.__init__
在调用方的线程中执行(例如,t = Test()
执行的线程(。是的,这是创建线程本地存储 (TLS( 的好地方。
但是当t.run
执行时,它将具有完全不同的内容 - 只能在线程t
中访问的内容。
当您需要在当前线程范围内共享数据时,TLS 很好。它就像函数中的一个局部变量 - 但用于线程。当线程完成执行时 - TLS 消失。
对于线程间通信,期货可能是一个不错的选择。其他一些是条件变量、事件等。请参阅线程文档页面。