python字典是线程安全的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3358770/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python dictionary is thread safe?
提问by Thien
Some stated that python dictionary is thread safe. Does it mean I can or cannot modify the items in a dictionary while iterating over it?
有人说python字典是线程安全的。这是否意味着我可以或不能在迭代时修改字典中的项目?
采纳答案by deinst
The two concepts are completely different. Thread safetymeans that two threads cannot modify the same object at the same time, thereby leaving the system in an inconsistent state.
这两个概念是完全不同的。 线程安全意味着两个线程不能同时修改同一个对象,从而使系统处于不一致的状态。
That said, you cannot modify a dictionary while iterating over it. See the documentation..
也就是说,您不能在迭代字典时修改它。请参阅文档。.
The dictionary p should not be mutated during iteration. It is safe (since Python 2.1) to modify the values of the keys as you iterate over the dictionary, but only so long as the set of keys does not change.
字典 p 不应该在迭代过程中发生变异。在迭代字典时修改键的值是安全的(自 Python 2.1 起),但前提是键集不更改。
回答by John La Rooy
No. Recent version of python will raise an exception if you try to iterate over a dictionary that has changed size between iterations.
不可以。如果您尝试迭代已在迭代之间更改大小的字典,则最新版本的 python 将引发异常。
>>> d={'one':1, 'two':2}
>>> for x in d:
... d['three']=3
... print x
...
two
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
Notice that you don't need to use threads to see this
请注意,您不需要使用线程来查看此内容
回答by Alex Martelli
The other answers already correctly addressed what's apparently your actual question:
其他答案已经正确解决了您的实际问题:
Does it mean I can or cannot modified the items in a dictionary while iterating over it?
这是否意味着我可以或不能在迭代时修改字典中的项目?
by explaining that thread safety has nothing to do with the issue, andin any case, no, you cannot modify a dict while iterating over it.
解释说,线程安全无关这个问题,并且在任何情况下,不,你不能在遍历它修改的字典。
However, the title of your question isabout thread safety, and you start with:
但是,您的问题的标题是关于线程安全的,您从以下内容开始:
Some stated that python dictionary is thread safe
有人说python字典是线程安全的
I don't know who the "some" are, but, if they did state that (rather than you misunderstanding what they did state;-) without heavy qualifications, they're wrong.
我不知道“一些”是谁,但是,如果他们确实声明了(而不是您误解了他们声明的内容;-)而没有严格的资格,那他们就错了。
Someoperations, those which don't alter the set of keys in the dict, happen to be thread-safe in current CPython implementations -- but you should notcount on that, unless you strictly control the Python version under which your code will run, because such thread safety is not guaranteed by Python's language specification and therefore other implementations, including future versions of CPython, might not offer it.
一些操作,那些不改变键组在快译通,恰好是线程安全的在当前的CPython实现-但你应该没有指望,除非你严格控制Python版本下,你的代码将运行,因为 Python 的语言规范不保证这种线程安全性,因此其他实现,包括 CPython 的未来版本,可能不会提供它。
If every thread is only "reading" the dict (indexing it, looping on it, etc), and no thread performs any assignment or deletion on it, then that situation is safe in current CPython implementations; in fact, if some thread assigns a new value to a key that was already present, that is also thread safe (other threads may see the previous value for that key, or the next one, depending on how the threads happen to be timed, but there will be no crash, no deadlock, and no appearance of crazy values out of nowhere, in current CPython implementations).
如果每个线程都只是“读取”字典(索引它,循环它等等),并且没有线程对其执行任何赋值或删除,那么这种情况在当前的 CPython 实现中是安全的;事实上,如果某个线程为已经存在的键分配一个新值,这也是线程安全的(其他线程可能会看到该键的前一个值,或下一个,这取决于线程是如何计时的,但是在当前的 CPython 实现中不会有崩溃、没有死锁,也不会突然出现疯狂的值)。
However, an operation such as d[k] += 1(assuming k was previously present, and its value a number) is notproperly speaking thread safe (any more than other case of +=!) because it can be seen as d[k] = d[k] + 1-- it mighthappen that two threads in a race condition both read the old value of d[k], then increment it by one, and store the same new value in the slot... so the overall effect is to increment it only by one, and not by two as would normally occur.
但是,诸如d[k] += 1(假设 k 先前存在,并且其值为数字)之类的操作不能正确地说是线程安全的(比其他情况更+=!)因为它可以被视为d[k] = d[k] + 1-可能会发生两个线程竞争条件都读取 的旧值d[k],然后将其加一,并将相同的新值存储在插槽中......所以总体效果是只加一,而不是像通常发生的那样加二。
Back to your other question... "only reading" the dict, andassigning new values to keys that already existed in the dict, are also the things you can do in the body of a loop that iterates on the dict -- you can't alter the set of keys in the dict (you can't add any key, nor remove any key), but the specific operation of setting a new value for an existing key is allowed. The allowed operations in this case do include the +=that would be problematic in a threading situation. For example:
回到你的另一个问题......“只读取”字典,并为字典中已经存在的键分配新值,这也是你可以在迭代字典的循环体中做的事情——你可以't 更改字典中的键集(您不能添加任何键,也不能删除任何键),但允许为现有键设置新值的特定操作。在这种情况下允许的操作确实包括+=在线程情况下会出现问题的操作。例如:
>>> d = dict.fromkeys(range(5), 0)
>>> for k in d: d[k] += 1
...
>>> d
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1}
and thisbehavior is guaranteed by Python's standardized semantics, so different implementations of the language should all preserve it.
并且这种行为是由 Python 的标准化语义保证的,因此该语言的不同实现都应该保留它。
回答by don_vanchos
You cannot iterate over a dictionary if you addor deleteelements in the another thread concurrently. You can get "RuntimeError: dictionary changed size during iteration" or "KeyError" errors.
如果同时在另一个线程中添加或删除元素,则无法迭代字典。您可能会收到“RuntimeError:在迭代期间字典更改大小”或“KeyError”错误。
See live exampleand you can play with it.
查看实时示例,您可以使用它。
And yes, you can iterate, change values of elements, get elements of it without exceptions in different threads concurrently.
是的,您可以迭代,更改元素的值,同时在不同的线程中毫无例外地获取其中的元素。

