Некоторые заявили, что словарь python является потокобезопасным. Означает ли это, что я могу или не могу изменять элементы в словаре во время итерации по нему?словарь python является потокобезопасным?
ответ
Эти две концепции совершенно разные. Thread safety означает, что два потока не могут одновременно изменять один и тот же объект, тем самым оставляя систему в противоречивом состоянии.
Таким образом, вы не можете изменять словарь во время итерации по нему. См. documentation..
Словарь p не должен мутироваться во время итерации. Безопасно (начиная с Python 2.1) до изменять значения ключей при повторении по словарю, но только до тех пор, пока набор ключей не изменится.
Нет. Последняя версия 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
Обратите внимание, что вам не нужно использовать потоки, чтобы увидеть эту
Другие ответы уже правильно адресованное то, что по-видимому, ваш актуальный вопрос:
Означает ли это, что я могу или не может быть модифицирован элементы в словаре, а итерации по нему?
, объясняя, что безопасность потока не имеет ничего общего с вопросом, и в любом случае, нет, вы не можете изменить Dict в то время как итерация над ним.
Однако название вашего вопроса является о безопасности потока, и вы начинаете с:
Некоторые заявили, что питон словарь поточно
Я не знаю, кто «некоторые» есть, но если они заявили, что (вместо того, чтобы вы не понимаете, что они сделали, -), без тяжелой квалификации они ошибаются.
Некоторые операции, те, которые не изменяют набор ключей в Словаре, случается потокобезопасной в текущей реализации CPython - но вы должны не рассчитывать на том, что, если вы строго не контролировать Python, под которым будет работать ваш код, поскольку такая безопасность потоков не гарантируется спецификацией языка Python, и поэтому другие реализации, включая будущие версии CPython, могут не предлагать ее.
Если каждый поток только «читает» dict (индексирует его, зацикливает на нем и т. Д.), И ни один поток не выполняет какое-либо присвоение или удаление на нем, тогда эта ситуация безопасна в текущих реализациях CPython; на самом деле, если какой-либо поток назначает новое значение ключу, который уже присутствует, это также потокобезопасно (другие потоки могут видеть предыдущее значение для этого ключа или следующего в зависимости от того, как потоки будут синхронизированы, но не произойдет ни крушения, ни тупика, ни появления сумасшедших ценностей из ниоткуда, в текущих реализациях CPython).
Однако операция, такие как d[k] += 1
(предполагается, что к ранее присутствует, и его значение числа) является не собственно говоря Потокобезопасная (больше, чем другой случай +=
!), Потому что это можно рассматривать как d[k] = d[k] + 1
- - это может произойдет, что два потока в состоянии гонки оба прочитали старое значение d[k]
, а затем увеличьте его на единицу и сохраните то же новое значение в слоте ... так что общий эффект состоит в том, чтобы увеличить его только на один , а не на два, как обычно.
Назад к другому вопросу ... «только чтение» dict, и присвоение новых значений ключам, которые уже существовали в dict, также являются тем, что вы можете сделать в теле цикла, который выполняет итерацию на dict - вы не можете изменять набор ключей в dict (вы не можете добавить ни один ключ, ни удалить любую клавишу), но разрешена конкретная операция установки нового значения для существующего ключа. Разрешенные операции в этом случае включают +=
, что было бы проблематично в ситуации с потоками. Например:
>>> d = dict.fromkeys(range(5), 0)
>>> for k in d: d[k] += 1
...
>>> d
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1}
и это поведение гарантируется стандартизованных семантики Python, так что различные реализации языка все должны сохранить его.
Вы сначала сказали: «Если каждый поток только« читает »dict (индексирует его, зацикливает на нем и т. Д.), И ** нить нить выполняет какое-либо присвоение или удаление на нем, тогда эта ситуация безопасна в текущих реализациях CPython ** », и, в конце концов, вы сказали, что« определенная операция ** установки нового значения для существующего ключа разрешена ... и это поведение гарантируется стандартизованной семантикой Python **, поэтому всевозможные реализации языка должны сохранять Это". Мне трудно различать два сценария. Не могли бы вы рассказать немного больше? Заранее спасибо! – RayLuo
Я думаю, что они связаны. Что делать, если один поток итерации, а другой изменяет dict? –