2010-07-29 2 views

ответ

28

Эти две концепции совершенно разные. Thread safety означает, что два потока не могут одновременно изменять один и тот же объект, тем самым оставляя систему в противоречивом состоянии.

Таким образом, вы не можете изменять словарь во время итерации по нему. См. documentation..

Словарь p не должен мутироваться во время итерации. Безопасно (начиная с Python 2.1) до изменять значения ключей при повторении по словарю, но только до тех пор, пока набор ключей не изменится.

+3

Я думаю, что они связаны. Что делать, если один поток итерации, а другой изменяет dict? –

13

Нет. Последняя версия 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 

Обратите внимание, что вам не нужно использовать потоки, чтобы увидеть эту

58

Другие ответы уже правильно адресованное то, что по-видимому, ваш актуальный вопрос:

Означает ли это, что я могу или не может быть модифицирован элементы в словаре, а итерации по нему?

, объясняя, что безопасность потока не имеет ничего общего с вопросом, и в любом случае, нет, вы не можете изменить 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, так что различные реализации языка все должны сохранить его.

+0

Вы сначала сказали: «Если каждый поток только« читает »dict (индексирует его, зацикливает на нем и т. Д.), И ** нить нить выполняет какое-либо присвоение или удаление на нем, тогда эта ситуация безопасна в текущих реализациях CPython ** », и, в конце концов, вы сказали, что« определенная операция ** установки нового значения для существующего ключа разрешена ... и это поведение гарантируется стандартизованной семантикой Python **, поэтому всевозможные реализации языка должны сохранять Это". Мне трудно различать два сценария. Не могли бы вы рассказать немного больше? Заранее спасибо! – RayLuo