我正在编程一个电报机器人,其中更多的线程处理每个更新异步。我硬编码一个空字典,当机器人运行时,多个线程写入和读取它。
最常见的操作是:
if key not in dict:
dict[key] = value
else:
dict[key].append(another_value)
问题是,当一个线程检查dict中是否存在密钥,而且可能不是,另一个线程在其中写入了密钥。
所以基本上我必须摆脱这种竞争条件。
我需要快速的解决方案。在网上搜索我找到了关于threading.Lock()
的答案。这些答案大约有10年的历史。我想知道现在它仍然是一个很好的解决方案,或者可能还有一些新的库
您可以使用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()
版本可能会更好。
Python的dicts对于单个操作是安全的,但是多个操作不是。您目前正在做的是多个操作。锁很好,通常是处理这个问题的标准方法。
看一看这里有关Python的线程安全的一些细节。
http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm