python - 我应该为仅存在于 {class,method} 中的变量使用线程本地存储吗?

标签 python concurrency namespaces multithreading

我正在使用 Python 的 Queue.Queue 类实现一个相对简单的线程池。我有一个生产者类,其中包含 Queue 实例以及一些方便的方法,还有一个消费者类是 threading.Thread 的子类。我根据一个整数为池中我想要的每个线程(“工作线程”,我认为它们被称为)实例化该对象。

每个工作线程从队列中取出flag, data,使用自己的数据库连接对其进行处理,并将该行的 GUID 放入列表中,以便生产者类知道作业何时完成.

虽然我知道其他模块实现了我编写的功能,但我编写此代码的原因是为了更好地了解 Python 线程的工作原理。这引出了我的问题。

如果我在函数的命名空间或类的 __dict__ 对象中存储任何内容,它会是线程安全的吗?

class Consumer(threading.Thread):
    def __init__(self, producer, db_filename):
        self.producer = producer
        self.conn = sqlite3.connect(db_filename)  # Is this var thread safe?
    def run(self):
        flag, data = self.producer.queue.get()

        while flag != 'stop':
            # Do stuff with data; Is `data` thread safe?

我认为两者都是线程安全的,这是我的理由:

  • 每次实例化一个类时,都会创建一个新的 __dict__。在我上面概述的场景下,我认为任何其他对象都不会引用该对象。 (现在,如果我使用 join() 功能,情况可能会变得更复杂,但我没有……)
  • 每次调用函数时,它都会创建自己的 namespace ,该 namespace 在函数的生命周期内存在。我没有将我的任何变量设为 global,因此我不明白任何其他对象如何引用函数变量。

This post稍微解决了我的问题,但对我来说仍然有点抽象。

预先感谢您为我解决这个问题。

最佳答案

你是对的;这是线程安全的。局部变量(您称为“函数命名空间”的变量)始终是线程安全的,因为只有执行该函数的线程才能访问它们。只要实例不跨线程共享,实例属性就是线程安全的。由于消费者类继承自Thread,其实例当然不会跨线程共享。

这里唯一的“风险”是数据对象的值:理论上,生产者可能会在将数据对象放入队列后保留该数据对象,并且(如果数据对象本身是可变的 - 确保您了解什么“可变”是指)可能会在消费者使用对象时更改对象。如果生产者在将数据对象放入队列后不理会它,这是线程安全的。

关于python - 我应该为仅存在于 {class,method} 中的变量使用线程本地存储吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1185117/

相关文章:

java - singlethreadexecutor - 多线程 java

java - 从 ConcurrentMap.remove() 获取键是否存在

git - Google 容器构建器,为新分支创建新命名空间

python - 设置 Google Adwords API 的客户 ID

python - 在 Sqlalchemy 中进行枚举的最佳方法?

python - 获得相似的词不再适用于 spacy

java - 同步多个计时器以提高/降低速度

python - 如何使用列表值创建颜色渐变一维热图(带状图)?

php - 无法在 PHP 中导入/使用命名空间函数

vb.net - 修复 'Error class is ambiguous in the namespace' 保持其模糊性