Why is the 'append' method of Python 'list' atomic while i = i + 1 is not atomic?

Viewed 338

According to the Python Documentation, the append operation on Python list is atomic. At the same time addition operation is not atomic:

i = i + 1

I understand that the Python GIL is enforcing the append operation to be atomic. My question is why the GIL is not enforcing the same on addition operation?

Consider the following code:

In [24]: L = []

In [25]: def func1():
    ...:     L.append(2)
    ...:

In [26]: i = 0

In [27]: def func2():
    ...:     i = i + 2
    ...:

The bytecode of both functions are shown below:

In [28]: dis.dis(func1)
  2           0 LOAD_GLOBAL              0 (L)
              2 LOAD_METHOD              1 (append)
              4 LOAD_CONST               1 (2)
              6 CALL_METHOD              1
              8 POP_TOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE

In [29]: dis.dis(func2)
  2           0 LOAD_FAST                0 (i)
              2 LOAD_CONST               1 (2)
              4 BINARY_ADD
              6 STORE_FAST               0 (i)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

Python ensures that thread switch happens only between bytecode instructions. What is the difference in the bytecode instructions that make append operation atomic?

1 Answers

Because the append operation side-effects the list being appended to, and if it were not atomic it would have have no chance of having any semantics (and a good chance of dumping core). Addition, by contrast, is a much simpler process, and also is commutative, so doing i+=1 in one thread and i-=1 in another will give the same final result when the smoke clears.

Related