python:如果键不在字典中,则添加键。防止多线程竞争条件

python: if key not in dictionary add the key. preventing race conditions with multiple threads

我正在编写一个电报机器人程序,其中有更多线程处理每个异步更新。 我硬编码了一个空字典,当机器人 运行 时,多个线程写入和读取它。

最常见的操作是:

if key not in dict:
    dict[key] = value
else:
    dict[key].append(another_value)

问题是,当一个线程检查 key 是否在 dict 中时,也许不是,另一个线程将 key 写入其中。

所以基本上我必须摆脱这种赛车状况。

我需要一个快速的解决方案。在网上搜索我找到了关于 threading.Lock() 的答案。这些答案大约有 10 年历史了。我想知道现在它是否仍然是一个很好的解决方案,或者也许有更多的新库

Python的dict对于单次操作是安全的,但是对于多次操作则不然。你目前正在做的是多项操作。锁很好,通常是处理这个问题的标准方法。

在这里查看有关 Python 线程安全的一些详细信息。

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm

您可以使用 defaultdict 或者,如果您想使用常规字典,则可以使用 setdefault() 方法。

使用defaultdict:

from collections import defaultdict
mydict = defaultdict(list)    # new key is initialized with an empty list
mydict[key].append(value)     # so it is always safe to append

使用setdefault()

mydict = {}
mydict.setdefault(key, []).append(value)

两者都应该是线程安全的,IIRC,即使它们看起来不是那样:方法实现在 C 中,因此不能被 Python 代码中断。因此,永远不可能有两个 setdefault() 方法同时执行并导致竞争条件。

通常首选 defaultdict,因为它性能更高,仅在需要时生成空列表,并且生成的代码更简单。如果您字典中的某些键可能具有非列表值,setdefault() 版本可能会更好。