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()
版本可能会更好。
我正在编写一个电报机器人程序,其中有更多线程处理每个异步更新。 我硬编码了一个空字典,当机器人 运行 时,多个线程写入和读取它。
最常见的操作是:
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()
版本可能会更好。