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

Является ли переменная 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)

4b9b3361

Ответ 1

Посмотрим:

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

Ответ 2

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

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

Краген Ситакер пишет:

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

spam, eggs = eggs, spam
     

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

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

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

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

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

- - David