如何在Python中使用线程本地存储?
相关
-
What is “thread local storage” in Python, and why do I need it? - 当共享变量时,此线程似乎更多地关注 .
-
Efficient way to determine whether a particular function is on the stack in Python - Alex Martelli给出了一个很好的解决方案
如何在Python中使用线程本地存储?
What is “thread local storage” in Python, and why do I need it? - 当共享变量时,此线程似乎更多地关注 .
Efficient way to determine whether a particular function is on the stack in Python - Alex Martelli给出了一个很好的解决方案
4 回答
例如,如果您有一个线程工作池,并且每个线程都需要访问自己的资源(如网络或数据库连接),则线程本地存储很有用 . 请注意,
threading
模块使用常规的线程概念(可以访问进程全局数据),但由于全局解释器锁定,这些概念不太有用 . 不同的multiprocessing
模块为每个创建一个新的子流程,因此任何全局都将是线程本地的 .线程模块
这是一个简单的例子:
这将打印出来:
一个很容易被忽视的重要事情是:一个
threading.local()
对象只需要创建一次,不是每个线程一次,也不是每个函数调用一次 .global
或class
级别是理想的位置 .原因如下:
threading.local()
实际上每次调用时都会创建一个新实例(就像任何工厂或类调用一样),因此多次调用threading.local()
会不断覆盖原始对象,这很可能不是人们想要的 . 当任何线程访问现有的threadLocal
变量(或其所谓的任何变量)时,它将获得该变量的私有视图 .这不会按预期工作:
将导致此输出:
多处理模块
所有全局变量都是线程本地的,因为
multiprocessing
模块为每个线程创建一个新进程 .考虑这个例子,其中
processed
计数器是线程本地存储的一个例子:它将输出如下内容:
...当然,每个和订单的线程ID和计数因运行而异 .
正如问题所述,Alex Martelli给出了解决方案here . 此函数允许我们使用工厂函数为每个线程生成默认值 .
线程局部存储可以简单地被认为是命名空间(通过属性表示法访问值) . 不同之处在于每个线程透明地获取自己的一组属性/值,因此一个线程不会看到另一个线程的值 .
就像普通对象一样,您可以在代码中创建多个
threading.local
实例 . 它们可以是局部变量,类或实例成员或全局变量 . 每个都是一个单独的命名空间 .这是一个简单的例子:
输出:
注意每个线程如何维护自己的计数器,即使
ns
属性是类成员(因此在线程之间共享) .同一个例子可能使用了一个实例变量或一个局部变量,但这并没有显示太多,因为当时没有共享(一个dict也能正常工作) . 在某些情况下,您需要将线程局部存储作为实例变量或局部变量,但它们往往相对较少(而且非常微妙) .
也可以写
mydata.x只存在于当前线程中