I don't think "atomic" is really what you're interested in.
If you're not using CPython (or you are, but one of the threads is running C code that's not under the GIL…), it is definitely not atomic, but it may be safe anyway under certain conditions.
If you are using CPython, it's atomic in the sense that in
is a single bytecode op (COMPARE_OP 6
), and in the possibly more useful sense that the actual hash-table lookup itself definitely happens under the GIL, and any potential equality comparison definitely happens with an object that's guaranteed to be alive. But it may still be unsafe, except under certain conditions.
First, the higher-level operation you're doing here is inherently racy. If thread 1 can be doing d['foo'] = 3
or del d['foo']
at the same time thread 0 is calling 'foo' in d
, there is no right answer. It's not a question of atomic or not—there is no sequencing here.
But if you do have some kind of explicit sequencing at the application level, so there is a right answer to get, then you're only guaranteed to get the right answer if both threads hold the GIL. And I think that's what you're asking about, yes?
That's only even possible in CPython—and, even there, it amounts to guaranteeing that no object you ever put in a dict
could ever release the GIL when you try to hash
or ==
it, which is a hard thing to guarantee generally.
Now, what if the other thread is just replacing the value associated with a key, not changing the set of keys? Then there is a right answer, and it's available concurrently, as long as the dict
implementation avoids mutating the hash table for this operation. At least in versions of CPython up to whatever was released by Jul 29 '10. Alex Martelli indirectly guarantees that in his answer to python dictionary is thread safe?. So, in that restricted case, you are safe in CPython—and likely in other implementations, but you'd want to read the code before relying on that.
As pointed out in the comments, the key you may end up comparing your lookup value with isn't guaranteed to be immutable, so even if the other thread doesn't do anything that changes the set of keys, it's still not absolutely guaranteed that you'll get the right answer. (You may have to craft a pathological key type to make this fail, but it would still be a legal key type.)