哪种方法最适合用于 python (CPython) 中多线程环境的线程安全全局存储?

问题描述

我有以下要求:

global_storage = "some_global_storage_system"

def call_me():
    global_storage += 1
    if global_storage > 1000:
        with threading.Lock():
            global_storage = 0 # reset global storage
            # performing some action
    

以上代码可以被5个线程同时访问

我找到了很多方法来这样做,但没有将它们收集在一个地方,并且没有提到以下哪一种方法是在上述程序中实现 global_storage 之类的最佳和最安全的方法

  1. 使用 python queues 库(因为它是线程安全的,但可能是内存问题):每次将一个项目放入队列,并在队列长度变为 1000 时检查,然后再次将队列长度设为 0。
  2. 在全局级别使用 dictionarycpython 中的线程安全):制作字典,global_dict["count"]=0,每次更新 global_dict["count"]++,然后读取 global_dict["count"]>1000。立>
  3. 使用 global 变量,使用 global 关键字(社区似乎最不推荐的一个
  4. 使用redis(避免因为它是网络调用的额外负担):在开始时使用redis.set(),在获取值时使用redis.get()
  5. 使用 threading.local 对象(感觉是最安全的对象),但我可能需要将检查计数减少到 200 才能获得相同的结果。

解决方法

您需要意识到操作 ((Long)object).longValue(); 可能不是在您想到的任何“some_global_storage_system”的几乎任何实现中的原子操作。如果 global_storage += 1 是一个 global_storage,它当然不是原子的,而且你不能得到比这更基本的东西。这意味着这个操作也需要在一个锁下进行序列化。

在以下代码中,我在全局范围内创建了一个名为 intthreading.Lock 实例,所有线程都可以访问该实例并用于序列化对 global_storage_lock 的访问。我向您提出的唯一(修辞)问题涉及您在获得锁时当前拥有的标记为 global_storage 的评论。通常,您希望在尽可能短的时间内持有锁。如果您不需要在此操作期间更新 #performing some action,请在锁定将被释放的此块之外执行该操作。

global_storage

下面是一个示例,说明在将 import threading global_storage_lock = threading.Lock() global_storage = "some_global_storage_system" def call_me(): with global_storage_lock: global_storage += 1 if global_storage > 1000: global_storage = 0 # reset global storage # performing some action 重置为 0 后需要执行操作时,您可以如何处理不需要锁定保持获取状态:

global_storage

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...