2012-05-15 32 views
5

我有一个字典正在由一个线程更新,而在另一个线程中,我想重复其值。通常我会使用一个锁,但是这个代码对性能非常重要,如果可能的话我想避免这种情况。一个人可以迭代正在被另一个线程修改的字典而不会引发异常吗?

我的情况的一个特点是我不关心迭代器的绝对正确性;如果它错过了迭代开始后删除的条目,或者选择了之后添加的条目,那很好。我只要求它不会引发任何'在迭代过程中更改的字典大小'异常。

鉴于这种放宽正确性的限制,有没有一种有效的方法来迭代字典而不使用锁?

注意:我知道keys()在Python 2.x中是线程安全的,但是由于3.x中的行为已经发生变化,我想避免它。

+0

如果你“只管去做”会发生什么? –

+3

谈到并发性,我宁愿按照事实工作而不是随机实验。 – DNS

+1

考虑到全局解释器锁的影响,锁定你的字典锁可能并不像你想象的那么昂贵(因为你的两个线程不会同时运行)。 – NPE

回答

4

没有与此个人的经验,但我读到这一段时间前:http://www.python.org/dev/peps/pep-3106/

These operations are thread-safe only to the extent that using them in a thread-unsafe way may cause an exception but will not cause corruption of the internal representation.

As in Python 2.x, mutating a dict while iterating over it using an iterator has an undefined effect and will in most cases raise a RuntimeError exception. (This is similar to the guarantees made by the Java Collections Framework.)

2

两件事情:

  1. 转储键进入queue和阅读安全。
  2. 性能关键的代码可能不应该使用Python线程。
+0

队列内部锁定,并且往往比直接使用锁定的性能明显更差。对于不使用Python线程你可能是正确的,但是这个决定是基于其他一些约束条件的,并且与问题无关。 – DNS

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.塞巴斯蒂安suggesion略低于转述:

while True: 
    try: 
     values = list(the_dict.values()) 
     break 
    except RuntimeError: 
     pass 

我个人会去的锁。

+0

你可以做'while True:\ n try:values = list(the_dict.values())\ n除了RuntimeError:pass \ n else:break' – jfs

相关问题