如果字典在迭代期间使用iteritems()
更改其大小,Python会引发异常。
由于我的程序是多线程,我遇到了这个问题,并且有些情况需要迭代dict
,而另一个线程正在向dict
添加密钥
幸运的是,我不需要迭代对dict
中的每个元素都非常精确。因此,我打算使用items()
而不是iteritems()
来进行迭代。我认为items()
制作了dict
的静态快照,我会解决这个问题。
我的问题是:如果items()
大小在dict
执行的同时发生变化,items()
是否会引发异常?
感谢
答案 0 :(得分:0)
正如出色的评论所指出的那样:
这不是线程安全的。
在做这些事情时你应该使用锁。
可以在the CPython source code, dictobject.c
中看到这一点:
如果你看一下这个功能
static PyObject *
dict_items(register PyDictObject *mp)
用于items
,您可以看到(在对结果进行了一些聪明的预分配之后),它基本上遍历数组mp->ma_table
(使用掩码查看有条目的位置) )。
现在,如果你看一下这个功能
static int
dictresize(PyDictObject *mp, Py_ssize_t minused)
当需要调整表的大小时使用,然后您可以看到ma_table
的元素可以移动到完全不同的缓冲区中,然后可以使用PYMem_Free
释放它。 / p>
因此,如果事情是在没有同步的情况下同时完成的,那么你就有很大的访问垃圾内存的风险。
答案 1 :(得分:0)
Python 2 的 CPython 实现中的items()
方法可以保证成功。
由于items()
方法在 C 中是implemented purley,而没有事先释放GIL
或在其执行期间释放,因此没有其他线程可以获取它和基础执行此方法时,数据结构保持不变。