Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify if one step is Atomic operation in python or now [duplicate]

Tags:

python

Is operation like a,b=1,2 atomic ?

Some background of my issue :I am working with signal . which are being raised from some external process. Here i want to avoid the cases when signal is being captured between setting a=1 and b=2. Is there any way to achieve this ?

Is there any way to check if given step is atomic or not ?

like image 408
gsagrawal Avatar asked Aug 01 '13 09:08

gsagrawal


People also ask

Are Python operations atomic?

Although some operations are atomic in Python, we should never rely on an operation being atomic. There are a number of good reasons for this, such as: The operations may not be atomic if the code is executed by a different Python interpreter. The behavior of the reference Python interpreter may change in the future.

Is Python variable assignment Atomic?

So the assignment is a single python bytecode (instruction 2), which is atomic in CPython since it executes one bytecode at a time. += corresponds to 4 instructions, which is not atomic.


2 Answers

It is not atomic because it takes multiple bytecode instructions to assign to multiple names and it doesn't take long to confirm it experimentally:

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

In this particular case, if you want two values to change atomically, you can get away with assignment to tuple and accessing its elements in the signal handler. Looking at disassembly:

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

No matter how complex the value is, assignment to a variable (or dict entry, or object field) is a single atomic store operation.

like image 117
rkhayrov Avatar answered Oct 03 '22 10:10

rkhayrov


No, the sequence assignment is not atomic. Just take a look at the byte code:

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

The assignment takes multiple opcodes to evaluate the tuple and store the result in variables.

like image 42
Rohit Jain Avatar answered Oct 03 '22 09:10

Rohit Jain