3

检查一个键是否在字典中if key in mydict- 一个原子操作?

如果没有,如果一个线程正在检查一个键,而另一个线程正在修改字典,是否会有任何负面影响?检查线程不会修改字典,它只是根据键的存在而有所不同。

4

1 回答 1

4

我认为“原子”并不是您真正感兴趣的。

如果您没有使用 CPython(或者您正在使用,但其中一个线程正在运行不在 GIL 下的 C 代码……),它绝对不是原子的,但在某些条件下它可能是安全的。

如果您使用的CPython ,它在某种意义上是原子的,即in单个字节码操作(COMPARE_OP 6保证活着的对象。但它可能仍然不安全,除非在某些条件下。

首先,您在这里执行的更高级别的操作本质上是活泼的。如果线程 1 可以做d['foo'] = 3del d['foo']同时线程 0 正在调用'foo' in d,则没有正确答案。这不是原子与否的问题——这里没有排序。

但是,如果您在应用程序级别确实有某种显式排序,那么就有了正确的答案,那么只有当两个线程都持有 GIL 时,您才能保证获得正确的答案。我这就是你要问的,是吗?

这甚至只有在 CPython 中才有可能——即使在 CPython 中,它也等于保证dict当你尝试hash==它时,你曾经放入的任何对象都不会释放 GIL,这通常是很难保证的。

现在,如果另一个线程只是替换与键关联的值,而不是更改键集怎么办?然后有一个正确的答案,它是并发可用的,只要dict实现避免改变这个操作的哈希表。至少在 2010 年 7 月 29 日之前发布的 CPython 版本中。Alex Martelli 间接保证在他对python 字典的回答中是线程安全的?. 因此,在这种受限情况下,您在 CPython 中是安全的——并且可能在其他实现中是安全的,但您需要在依赖它之前阅读代码。

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.)

于 2012-12-29T02:12:26.240 回答