Является ли вариабельный своп, гарантированно быть атомным в Python?

StackOverflow https://stackoverflow.com/questions/2623086

Вопрос

Со ссылкой на следующую ссылку: http://docs.cython.org/faq/library.html#what-kinds-of-global-value-muta-are-reat-tread-safe.

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

(x, y) = (y, x)

Будет гарантирован атомным в CPYthon. (x и y - оба переменные Python)

Это было полезно?

Решение

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

>>> 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

Другие советы

Да, да, это будет.

Я стою исправлено.

Kragen Citaker пишет:

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

spam, eggs = eggs, spam

чтобы получить потоковую сумму. Это действительно работает? (...)
Так что если эта нить теряет контроль в любом месте между первой Load_Fast
и последний Store_fast, значение может быть сохранено другим потоком
в «B», который тогда будет потерян. Нет ничего сохранять это
От происхождения есть?

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

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

С этим сказал, Python также имеет тенденцию выполнять таким образом, что вы можете сойти с ужасным большим количеством без формального блокировки, если вы готовы жить на краю немного и подразумевали зависимости от реальных объектов в использовании. Отказ Здесь было приличное обсуждение вдоль этих строк здесь, в CLP A, когда обратно - поисковые группы. Google.com для «критических разделов и нити Mutexes» среди прочего.

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

-- -- Дэйвид

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top