Безпека теми в словнику Python


105

У мене є клас, який містить словник

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?


2
як могла виникнути проблема, коли кожна тема нині не пише в інший ключ.
Jochen Ritzel

63
@Jochen: залежно від того, як виконуються дикти, багато може піти не так. Це дуже розумне питання.
Нед Батчелдер

Відповіді:


95

Вбудовані структури Python є безпечними для потоків для одиночних операцій, але іноді буває важко зрозуміти, де оператор дійсно стає декількома операціями.

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

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm має більш детальну інформацію.


6
Ось effbot.org чому-до / як-як упровадити замок
варильні панелі

1
Слід враховувати одиночну операцію проти складених операцій, таких як get-add-set .
andy

5
Проблема полягає в тому, що, коли я часто читаю / пишу цей диктант, цей спокій коштуватиме мені дорого.
Шихаб Шахріар-хан

2
"замок тут майже не додасть накладних витрат": чому це?
макс

32

Так, вбудовані типи по суті є безпечними для потоків: http://docs.python.org/glossary.html#term-global-interpreter-lock

Це спрощує реалізацію CPython, роблячи об'єктну модель ( включаючи критичні вбудовані типи, такі як dict ), неявно безпечною від паралельного доступу.


25
Це не особливість Python, а cpython .
фігаг

8
Щоправда, але, наскільки я розумію, вбудовані в Jython та IronPython також є безпечними для потоків навіть без використання GIL (і ненавантажена ластівка, якщо вона коли-небудь з’явиться, пропонує також покінчити з GIL). Я припускав, що оскільки він не вказав перекладача, яким він користується, він мав на увазі в CPython.

1
Правильно у випадку Jython: jython.org/jythonbook/en/1.0/…
Євгеній Сергєєв

9

Посібник зі стилів Google радить не покладатися на атомність

Детальніше пояснено на: Чи атомним є призначення змінної Python?

Не покладайтеся на атомність вбудованих типів.

У той час як Python вбудовані типи даних , такі як словники , як видається, атомарні операції, є випадки , кут , де вони не є атомарними (наприклад , якщо __hash__або __eq__реалізовані як методи Python) і їх валентність не слід покладатися. Не слід також покладатися на призначення атомних змінних (оскільки це в свою чергу залежить від словників).

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

І я погоджуюся з цим: GIL у CPython вже є, тож ефективність використання Lock буде незначною. Набагато дорожче коштуватимуть години на пошук помилок у складній кодовій базі, коли ці деталі впровадження CPython змінюються за один день.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.