如何验证一步是python中的原子操作还是现在

时间:2013-08-01 09:35:17

标签: python

a,b=1,2这样的操作是原子的吗?

我的问题的一些背景:我正在使用信号。这是从一些外部过程中提出来的。在这里,我想避免在设置a=1 and b=2之间捕获信号的情况。有没有办法实现这个目标?

有没有办法检查给定的步骤是否是原子的?

2 个答案:

答案 0 :(得分:12)

它不是原子的,因为它需要多个字节码指令来分​​配多个名称,并且不需要花很长时间才能通过实验确认:

import signal

a = 1
b = 2

def handler(sig, trace):
    print a, b

def main():
    global a, b
    signal.signal(signal.SIGINT, handler)
    while True:
        a, b = 3, 4
        a, b = 1, 2

if __name__ == '__main__':
    main()

$ python atom.py
^C3 4
^C3 4
^C1 2
^C1 2
^C3 4
^C1 2
^C1 2
^C1 2
^C1 2
^C1 4 <<<< inconsistent state

在这种特殊情况下,如果您希望两个值以原子方式更改,则可以通过赋值给元组并在信号处理程序中访问其元素。看看反汇编:

>>> a = 1
>>> b = 2
>>> c = (1, 2)
>>> def foo():
...     global a, b
...     a, b = 1, 2
... 
>>> def bar():
...     global c
...     c = (1, 2)
... 
>>> dis.dis(foo)
  3           0 LOAD_CONST               3 ((1, 2))
              3 UNPACK_SEQUENCE          2
              6 STORE_GLOBAL             0 (a)
              9 STORE_GLOBAL             1 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        
>>> dis.dis(bar)
  3           0 LOAD_CONST               3 ((1, 2))
              3 STORE_GLOBAL             0 (c)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

无论值多么复杂,赋值给变量(或dict条目或对象字段)都是单个原子库操作。

答案 1 :(得分:4)

不,序列分配不是原子的。只需看看字节码:

>>> def unpack():
        a,b=1,2

>>> import dis
>>> dis.dis(unpack)
  2           0 LOAD_CONST               3 ((1, 2))
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               0 (a)
              9 STORE_FAST               1 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        

赋值需要多个操作码来评估元组并将结果存储在变量中。