Безопасность потоков в словаре Python

У меня есть класс, в котором есть словарь

class OrderBook:
    orders = {'Restaurant1': None,
              'Restaurant2': None,
              'Restaurant3': None,
              'Restaurant4': None}

    @staticmethod
    def addOrder(restaurant_name, orders):
        OrderBook.orders[restaurant_name] = orders

И я запускаю 4 потока (по одному для каждого ресторана), которые вызывают метод OrderBook.addOrder. Вот функция, выполняемая каждым потоком:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)

Это безопасно, или мне нужно использовать блокировку перед вызовом addOrder?


person nmat    schedule 05.08.2011    source источник
comment
как может быть проблема, когда каждый поток все равно записывает на свой ключ.   -  person Jochen Ritzel    schedule 05.08.2011
comment
@Jochen: в зависимости от того, как реализованы диктовки, многое может пойти не так. Это очень разумный вопрос.   -  person Ned Batchelder    schedule 05.08.2011


Ответы (4)


Встроенные структуры Python являются потокобезопасными для отдельных операций, но иногда бывает трудно увидеть, где оператор действительно превращается в несколько операций.

Ваш код должен быть в безопасности. Имейте в виду: замок здесь почти не добавит накладных расходов и даст вам душевное спокойствие.

https://web.archive.org/web/20201108091210/http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm есть более подробная информация.

person Ned Batchelder    schedule 05.08.2011
comment
Вот почему effbot.org и инструкции по реализации блокировки - person hobs; 31.05.2014
comment
Следует рассмотреть отдельные операции по сравнению с составными операциями, такими как get-add-set. - person andy; 19.12.2014
comment
Проблема в том, что когда я часто читаю / пишу это изречение, душевное спокойствие будет мне дорого стоить. - person Shihab Shahriar Khan; 18.02.2017
comment
блокировка здесь почти не добавит накладных расходов: почему? - person max; 14.12.2019
comment
Ссылка мертва, см. Например здесь: titanwolf.org/ Сеть / Статьи / - person Ruli; 24.01.2021

Да, встроенные типы по своей сути являются потокобезопасными: http://docs.python.org/glossary.html#term-global-interpreter-lock.

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

person Community    schedule 05.08.2011
comment
Это особенность не Python, а cpython. - person phihag; 05.08.2011
comment
Верно, но, насколько я понимаю, встроенные в Jython и IronPython также потокобезопасны даже без использования GIL (и незагруженная ласточка, если она когда-либо появится, также предлагает покончить с GIL). Я предположил, что, поскольку он не указал используемый интерпретатор, он имел в виду в CPython. - person ; 05.08.2011
comment
Верно в случае Jython: jython.org /jythonbook/en/1.0/ - person Evgeni Sergeev; 06.03.2016

Руководство по стилю Google не рекомендует полагаться на атомарность диктовки

Более подробно описано на странице: Является ли присвоение переменных Python атомарным?

Не полагайтесь на атомарность встроенных типов.

В то время как встроенные типы данных Python, такие как словари, по-видимому, имеют атомарные операции, есть угловые случаи, когда они не являются атомарными (например, если __hash__ или __eq__ реализованы как методы Python) и на их атомарность не следует полагаться. Вы также не должны полагаться на присвоение атомарных переменных (поскольку это, в свою очередь, зависит от словарей).

Используйте тип данных Queue модуля Queue в качестве предпочтительного способа передачи данных между потоками. В противном случае используйте модуль потоковой передачи и его блокирующие примитивы. Узнайте о правильном использовании условных переменных, чтобы вы могли использовать threading.Condition вместо низкоуровневых блокировок.

И я согласен с этим: в CPython уже есть GIL, поэтому снижение производительности при использовании Lock будет незначительным. Гораздо дороже будут часы, потраченные на поиск ошибок в сложной кодовой базе, когда эти детали реализации CPython изменятся в один прекрасный день.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 07.04.2019

При использовании встроенного dict Python, set и get являются атомарными (из-за GIL cpython). Однако это кажется плохой практикой, поскольку такие операции, как .items, не являются атомарными.

Примечание. Операции get-add-set не являются потокобезопасными, если несколько потоков работают с одними и теми же ключами dict.

person ravi malhotra    schedule 13.06.2021