I'm wondering if dict.update() is Python thread safe. I've read the related questions, but none of them exactly addresses my question.
My question is very specific and simple. For example, I already have a local dictionary d2. I simply need to update the global dictionary d with d2 as shown below. d starts out empty and fills up with different threads. The d2 in each thread may have overlapping entries with d (don't think this matters). Is it thread safe?
import dis
def f(d):
d2 = {1:2, 3:4}
d.update(d2)
print(dis.dis(f))
The bytecode looks like the following:
10 0 LOAD_CONST 1 (2)
2 LOAD_CONST 2 (4)
4 LOAD_CONST 3 ((1, 3))
6 BUILD_CONST_KEY_MAP 2
8 STORE_FAST 1 (d2)
11 10 LOAD_FAST 0 (d)
12 LOAD_ATTR 0 (update)
14 LOAD_FAST 1 (d2)
16 CALL_FUNCTION 1
18 POP_TOP
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
It looks like 16 CALL_FUNCTION is the atomic function that updates the dictionary. So it should be thread safe?
If the keys are compositions of builtin hashable types, generally "yes", .update() is thread-safe. In particular, for your example with integers keys, yes.
But in general, no. Looking up a key in a dict can invoke arbitrary user-defined Python code in user-supplied __hash__() and __eq__() methods, and those can do anything at all - including performing their own mutations on the dicts involved. As soon as the implementation invokes Python code, other threads can run too, including threads that may be mutating d1 and/or d2 too.
That's not a potential problem for the builtin hashable types (ints, strings, floats, tuples, ...) - their implementations to compute hash codes and decide equality are purely functional (deterministic and no side effects) and don't release the GIL (global interpreter lock).
That's all about CPython (the C implementation of Python). The answer may differ under other implementations! The Language Reference Manual is silent about this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With