操作像a,b=1,2
原子吗?
我的问题的一些背景:我正在使用信号。这是从一些外部过程中提出的。在这里,我想避免在设置之间捕获信号的情况a=1 and b=2
。有没有办法做到这一点?
有没有办法检查给定的步骤是否是原子的?
操作像a,b=1,2
原子吗?
我的问题的一些背景:我正在使用信号。这是从一些外部过程中提出的。在这里,我想避免在设置之间捕获信号的情况a=1 and b=2
。有没有办法做到这一点?
有没有办法检查给定的步骤是否是原子的?
它不是原子的,因为它需要多个字节码指令来分配多个名称,并且不需要很长时间就可以通过实验确认它:
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
条目或对象字段)的赋值都是单个原子存储操作。
不,序列分配不是原子的。看一下字节码:
>>> 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
赋值需要多个操作码来评估元组并将结果存储在变量中。