Straight up dict
assignment is thread-safe
The GIL yields only in between python bytecode instructions. Operations that take only a single bytecode instruction are safe from the GIL yielding mid operation. dict
assignments only take a single operation.
In [4]: import dis
In [5]: x = {}
In [6]: def f():
...: x['test'] = 'test'
...:
In [7]: dis.dis(f)
2 0 LOAD_CONST 1 ('test')
3 LOAD_GLOBAL 0 (x)
6 LOAD_CONST 1 ('test')
9 STORE_SUBSCR #<<<<<<<< this OP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
If you need to do anything other than a write - in-place add, a read followed by a write, etc - then you're in trouble.
I would argue strongly that this is an implementation detail and actually depending on it to guarantee behavior is asking for trouble. Always provide explicit locks around shared data access.