检查一个键是否在字典中 - if key in mydict
- 是原子操作吗?
如果不是,如果一个线程正在检查键而另一个线程正在修改字典,是否会有任何负面影响?检查线程不会修改字典,它只是根据键的存在而表现不同。
最佳答案
我认为“原子”并不是您真正感兴趣的。
如果您没有使用 CPython(或者您正在使用,但其中一个线程正在运行不在 GIL 下的 C 代码……),它绝对不是原子的,但在某些条件下它可能是安全的。
如果您正在使用 CPython,它在 in
的意义上是原子的是单个字节码 op ( COMPARE_OP 6
),并且在可能更有用的意义上,实际的哈希表查找本身肯定发生在 GIL 下,并且任何潜在的相等比较肯定发生在保证存活的对象上。但它可能仍然不安全,除非在某些条件下。
首先,您在这里进行的高级操作本质上是活泼的。如果线程 1 可以做 d['foo'] = 3
或 del d['foo']
同时线程 0 正在调用 'foo' in d
, 没有正确的答案。这不是原子与否的问题——这里没有顺序。
但是,如果您在应用程序级别确实有某种显式排序,因此可以获得正确的答案,那么只有当两个线程都持有 GIL 时,您才能保证获得正确的答案。我认为这就是你要问的,是吗?
这甚至只有在 CPython 中才有可能——即使在 CPython 中,这也相当于保证您从未将任何对象放入 dict
中。当您尝试 hash
时可能会释放 GIL或 ==
它,这通常很难保证。
现在,如果另一个线程只是替换与键关联的值,而不是更改键集怎么办?那么是一个正确的答案,它是同时可用的,只要dict
实现避免为该操作改变哈希表。至少在 2010 年 7 月 29 日发布的 CPython 版本中。 Alex Martelli 在他对 python dictionary is thread safe? 的回答中间接保证.因此,在这种受限情况下,您在 CPython 中是安全的——并且可能在其他实现中是安全的,但您希望在依赖它之前阅读代码。
正如评论中所指出的,您可能最终将查找值与其进行比较的键不能保证是不可变的,因此即使另一个线程没有做任何改变键集的事情,它也是 仍然不能绝对保证您会得到正确答案。 (您可能必须设计一个病态的 key 类型才能使其失败,但它仍然是一个合法的 key 类型。)
关于python - 检查字典中的键是原子操作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14077688/