变量交换是否保证在python中是原子的?

时间:2010-04-12 15:11:53

标签: python multithreading atomic cpython

参考以下链接: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 个答案:

答案 0 :(得分:54)

让我们看看:

>>> 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之间的另一个线程来更改1}}字节码。

如果要以原子方式交换两个变量,则需要锁定或互斥锁。

对于那些渴望经验证明的人:

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

答案 1 :(得分:4)

是的,是的。

I stand corrected

  

Kragen Sitaker   写道:

     
    

有人推荐使用这个成语

spam, eggs = eggs, spam
         

获得线程安全交换。这真的有用吗? (...)
    因此,如果此线程在第一个LOAD_FAST之间失去控制权     和最后一个STORE_FAST,一个值可以由另一个线程存储     进入“b”然后会丢失。没有任何保持这一点     从发生,是吗?

  
     

不。一般来说甚至不简单   赋值必然是线程安全的   因为执行任务可能   在对象上调用特殊方法   他们自己可能需要一个号码   的运作。 希望是对象   将内部锁定它   “国家”价值观,但并非总是如此   案件。

     

但它确实取决于什么   “线程安全”是指特定的   申请,因为在我心中   这种粒度很多   安全所以很难谈   “线程安全”。关于唯一的事情   Python解释器即将发布   给你免费是内置的   数据类型应该是内部安全的   即使使用本机线程也会出现损坏   换句话说,如果有两个线程   a=0xffa=0xff00,结束了   与一个或另一个,但不是   意外地0xffff可能是   可能在其他一些语言中如果a   没有受到保护。

     

据说, Python也倾向于   以你可以这样的方式执行   在没有的情况下侥幸逃脱   正式锁定,如果你愿意的话   生活在边缘一点点   暗示对实际的依赖   正在使用的对象。有一个体面的   沿着这些方向进行讨论   c.l.p一会儿 - 搜索   groups.google.com为“关键   部分和互斥体之间的联系   其他

     

就个人而言,我明确锁定共享   状态(或使用为...设计的结构   正确交换共享信息   在线程中,例如Queue.Queue)   在任何多线程应用程序中。至   我认为这是最好的保护   反对维护和进化   这条路。

     

-    - David

相关问题