如何解决哪种方法最适合用于 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
之类的最佳和最安全的方法:
- 使用 python
queues
库(因为它是线程安全的,但可能是内存问题):每次将一个项目放入队列,并在队列长度变为 1000 时检查,然后再次将队列长度设为 0。 - 在全局级别使用
dictionary
(cpython 中的线程安全):制作字典,global_dict["count"]=0
,每次更新global_dict["count"]++
,然后读取global_dict["count"]>1000
。立> - 使用
global
变量,使用global
关键字(社区似乎最不推荐的一个) - 使用
redis
(避免因为它是网络调用的额外负担):在开始时使用redis.set()
,在获取值时使用redis.get()
- 使用
threading.local
对象(感觉是最安全的对象),但我可能需要将检查计数减少到200
才能获得相同的结果。
解决方法
您需要意识到操作 ((Long)object).longValue();
可能不是在您想到的任何“some_global_storage_system”的几乎任何实现中的原子操作。如果 global_storage += 1
是一个 global_storage
,它当然不是原子的,而且你不能得到比这更基本的东西。这意味着这个操作也需要在一个锁下进行序列化。
在以下代码中,我在全局范围内创建了一个名为 int
的 threading.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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。