Подтвердить что ты не робот

Словарь python является потокобезопасным?

Некоторые заявили, что словарь python является потокобезопасным. Означает ли это, что я могу или не могу изменять элементы в словаре, итерации по нему?

4b9b3361

Ответ 1

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

Тем не менее, вы не можете модифицировать словарь во время итерации по нему. См. Документацию ..

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

Ответ 2

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

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

объяснив, что безопасность потоков не имеет ничего общего с проблемой, и в любом случае, нет, вы не можете модифицировать dict во время итерации по ней.

Однако название вашего вопроса касается безопасности потоков, и вы начинаете с:

Некоторые заявили, что словарь python безопасный поток

Я не знаю, кто такие "некоторые", но, если они это заявили (вместо того, чтобы вы не понимали, что они сделали, -) без тяжелой квалификации, они ошибаются.

Некоторые операции, которые не изменяют набор ключей в dict, не являются потокобезопасными в текущих реализациях CPython, но вы должны not рассчитывать на это, если только вы строго управляйте версией Python, под которой будет работать ваш код, потому что такая безопасность потоков не гарантируется спецификацией языка Python, и поэтому другие реализации, включая будущие версии CPython, могут не предлагать ее.

Если каждый поток только "читает" dict (индексирует его, зацикливает на нем и т.д.), и ни один поток не выполняет какое-либо присвоение или удаление на нем, тогда эта ситуация безопасна в текущих реализациях CPython; на самом деле, если какой-либо поток назначает новое значение ключу, который уже присутствует, это также потокобезопасно (другие потоки могут видеть предыдущее значение для этого ключа или следующего в зависимости от того, как потоки будут синхронизированы, но не будет ни крути, ни тупика, ни появления сумасшедших ценностей из ниоткуда, в текущих реализациях CPython).

Однако операция, такая как d[k] += 1 (предполагая, что k ранее присутствовала, и ее значение число) не является корректным потокобезопасным (не более, чем другой случай +=!), поскольку его можно рассматривать как 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, поэтому различные реализации языка должны его сохранить.

Ответ 3

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

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