5

操作はa,b=1,2アトミックのようなものですか?

私の問題の背景:私は signal を扱っています。これは、何らかの外部プロセスから発生しています。ここで、設定の間に信号がキャプチャされるケースを避けたいと思いますa=1 and b=2。これを達成する方法はありますか?

特定のステップがアトミックかどうかを確認する方法はありますか?

4

2 に答える 2

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

この特定のケースで、2 つの値をアトミックに変更したい場合は、タプルへの代入とシグナル ハンドラーでの要素へのアクセスを回避できます。分解を見る:

>>> 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エントリ、またはオブジェクト フィールド) への割り当ては、単一のアトミック ストア操作です。

于 2013-08-01T09:46:32.280 に答える
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        

割り当ては、タプルを評価し、結果を変数に格納するために複数のオペコードを取ります。

于 2013-08-01T09:42:01.823 に答える