Является ли переменная swap гарантированно атомарной в python?

со ссылкой на следующую ссылку: http://docs.python.org/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe

Я хотел знать, если следующее:

(x, y) = (y, x)

будет гарантирован атомарный в cPython. (x и y являются переменными python)

2 ответов


давайте посмотрим:

>>> x = 1
>>> y = 2
>>> def swap_xy():
...   global x, y
...   (x, y) = (y, x)
... 
>>> dis.dis(swap_xy)
  3           0 LOAD_GLOBAL              0 (y)
              3 LOAD_GLOBAL              1 (x)
              6 ROT_TWO             
              7 STORE_GLOBAL             1 (x)
             10 STORE_GLOBAL             0 (y)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE    

не похоже, что они атомарные: значения x и y могут быть изменены другим потоком между LOAD_GLOBAL байт-коды, до или после ROT_TWO, и между STORE_GLOBAL байткод.

если вы хотите поменять две переменные атомарно, вам понадобится блокировка или мьютекс.

для желающих эмпирического доказательства:

>>> def swap_xy_repeatedly():
...   while 1:
...     swap_xy()
...     if x == y:
...       # If all swaps are atomic, there will never be a time when x == y.
...       # (of course, this depends on "if x == y" being atomic, which it isn't;
...       #  but if "if x == y" isn't atomic, what hope have we for the more complex
...       #  "x, y = y, x"?)
...       print 'non-atomic swap detected'
...       break
... 
>>> t1 = threading.Thread(target=swap_xy_repeatedly)
>>> t2 = threading.Thread(target=swap_xy_repeatedly)
>>> t1.start()
>>> t2.start()
>>> non-atomic swap detected

Да, да.

ошибка.

Краген Sitaker пишет:

кто-то рекомендовал использовать идиому

spam, eggs = eggs, spam

чтобы получить потокобезопасную замену. Это действительно работает? (...)
Поэтому, если этот поток теряет контроль в любом месте между первым LOAD_FAST
и последний STORE_FAST, значение может быть сохранено другим потоком
в "Б", которое затем будет потеряно. Нет ничего, что удерживало бы это
от происходящего там?

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

но это действительно продиктовано тем, что "безопасность резьбы" означает, в частности, применение, потому что на мой взгляд там много уровней детализации таких безопасности, поэтому трудно говорить о "безопасность потока." О единственном интерпретатор Python будет дать вам бесплатно - это встроенный тип данных должен быть защищен от внутренних коррупция даже с родной нитью. Другими словами, если два потока a=0xff и a=0xff00, a в конечном итоге с одним или с другим, но не случайно 0xffff как может быть возможно, в некоторых других языках, если не защищен.

С Python также имеет тенденцию к выполняйте так, чтобы вы могли уйти с Много без формальный замок, Если вы готовы жить на грани немного и иметь подразумеваемые зависимости от фактического используемые объекты. Был приличный дискуссии по этим направлениям здесь в c.l.p некоторое время назад-поиск groups.google.com для "Критический разделы и мьютексы" нить среди другие.

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

-- -- Дэвид