Search code examples
pythonpython-2.7concurrencyatomic

Is set.copy() atomic in Python?


Suppose we have an instance variable in a class.

class MyClass(object):  
    def __init__():  
        self.set1 = set()  

Is the following operation atomic?

set_shallow_copy = self.set1.copy()

I've tried to search around, but the only information I've found is that reading instance variables are atomic.

(Edit) I tried to decompile the bytecode (Python 2.7 on Windows), but it's not too useful. It just shows Python bytecode that calls the copy function on set.

 9 LOAD_FAST                0 (s)  
 12 LOAD_ATTR                1 (copy)  
 15 CALL_FUNCTION            0 
 18 STORE_FAST               1 (s2) 
 21 LOAD_CONST               0 (None) 
 24 RETURN_VALUE 

(Edit 2): I wonder if using set2 = set(set1) might be better.

         9 LOAD_GLOBAL              0 (set)  
         12 LOAD_FAST                0 (set1)  
         15 CALL_FUNCTION            1  
         18 STORE_FAST               1 (set2)  
         21 LOAD_CONST               0 (None)  
         24 RETURN_VALUE

Solution

  • In CPython since version 3.5, the copy is atomic as far as is visible from Python (because, as usual, of the global interpreter lock). No other thread can alter set1 while it is being copied, so you will obtain a copy of some state that the set was in during the manipulations made by (other) threads.

    In older versions (like the one tagged here!), the routine that added the elements of the original set to the new (initially empty) copy did not take advantage of the fact that, coming from a set, all the values were unique; as such, it uses == to rediscover that fact. If that comparison is implemented in Python (or by certain C extensions that release the GIL), then the process can be interrupted by other threads (and fail arbitrarily).