我有一个字典由一个线程更新,而在另一个线程中我想迭代它的值。通常我会使用锁,但这段代码对性能非常关键,我想尽可能避免这种情况。
我的案例的一个特点是我不关心迭代器的绝对正确性;如果它错过了在迭代开始后删除的条目,或者拾取了之后添加的条目,那很好。我只要求它不会引起任何类型的“在迭代期间更改的字典大小”异常。
鉴于对正确性的宽松约束,是否有一种有效的方法来迭代字典而不使用锁?
注意:我知道{2.}}在Python 2.x中是线程安全的,但由于该行为在3.x中发生了变化,我想避免它。
答案 0 :(得分:4)
没有个人经验,但我前段时间读过这篇文章:http://www.python.org/dev/peps/pep-3106/
这些操作只是在线程安全的情况下,以线程不安全的方式使用它们可能会导致异常,但不会导致内部表示损坏。
与Python 2.x一样,在使用迭代器迭代它时改变dict具有未定义的效果,并且在大多数情况下会引发RuntimeError异常。 (这类似于Java Collections Framework所做的保证。)
答案 1 :(得分:3)
我会考虑使用一个足够长的锁来检索你想要迭代的值:
with lock:
values = the_dict.values() # python 2
# values = list(the_dict.values()) # python 3
for value in values:
# do stuff
或者,您可以在没有锁定的情况下尝试它并捕获RuntimeError
,如果您得到一个,请尝试再次检索这些值。
[编辑]根据J.F.塞巴斯蒂安的建议,以下略有改写:
while True:
try:
values = list(the_dict.values())
break
except RuntimeError:
pass
我个人会带锁。
答案 2 :(得分:2)
两件事:
答案 3 :(得分:0)
有时候一个例子胜于文字。
数组迭代不是线程安全的,请参见live example for Python 3.6