Is the += operator thread-safe in Python?

后端 未结 8 1570
萌比男神i
萌比男神i 2020-11-27 13:45

I want to create a non-thread-safe chunk of code for experimentation, and those are the functions that 2 threads are going to call.

c = 0

def increment():
          


        
8条回答
  •  执念已碎
    2020-11-27 14:04

    (note: you would need global c in each function to make your code work.)

    Is this code thread safe?

    No. Only a single bytecode instruction is ‘atomic’ in CPython, and a += may not result in a single opcode, even when the values involved are simple integers:

    >>> c= 0
    >>> def inc():
    ...     global c
    ...     c+= 1
    
    >>> import dis
    >>> dis.dis(inc)
    
      3           0 LOAD_GLOBAL              0 (c)
                  3 LOAD_CONST               1 (1)
                  6 INPLACE_ADD         
                  7 STORE_GLOBAL             0 (c)
                 10 LOAD_CONST               0 (None)
                 13 RETURN_VALUE        
    

    So one thread could get to index 6 with c and 1 loaded, give up the GIL and let another thread in, which executes an inc and sleeps, returning the GIL to the first thread, which now has the wrong value.

    In any case, what's atomic is an implementation detail which you shouldn't rely on. Bytecodes may change in future versions of CPython, and the results will be totally different in other implementations of Python that do not rely on a GIL. If you need thread safety, you need a locking mechanism.

提交回复
热议问题