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.
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
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
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).
Please use automic_set in shared atomic enterprise
Python atomic for shared data types.
The module can be used for atomic operations under multiple processs and multiple threads conditions. High performance python! High concurrency, High performance!
atomic api Example with multiprocessing and multiple threads:
You need the following steps to utilize the module:
create function used by child processes, refer to UIntAPIs, IntAPIs, BytearrayAPIs, StringAPIs, SetAPIs, ListAPIs, in each process, you can create multiple threads.
def process_run(a): def subthread_run(a): a.array_sub_and_fetch(b'x0F') threadlist =  for t in range(5000): threadlist.append(Thread(target=subthread_run, args=(a,))) for t in range(5000): threadlist[t].start() for t in range(5000): threadlist[t].join()
create the shared bytearray
a = atomic_bytearray(b'ab', length=7, paddingdirection='r', paddingbytes=b'012', mode='m')
start processes / threads to utilize the shared bytearray
processlist =  for p in range(2): processlist.append(Process(target=process_run, args=(a,))) for p in range(2): processlist[p].start() for p in range(2): processlist[p].join() assert a.value == int.to_bytes(27411031864108609, length=8, byteorder='big')