是python dict.items()线程安全吗?

时间:2016-09-14 18:47:25

标签: python multithreading dictionary

如果字典在迭代期间使用iteritems()更改其大小,Python会引发异常。

由于我的程序是多线程,我遇到了这个问题,并且有些情况需要迭代dict,而另一个线程正在向dict添加密钥

幸运的是,我不需要迭代对dict中的每个元素都非常精确。因此,我打算使用items()而不是iteritems()来进行迭代。我认为items()制作了dict的静态快照,我会解决这个问题。

我的问题是:如果items()大小在dict执行的同时发生变化,items()是否会引发异常?

感谢

2 个答案:

答案 0 :(得分:0)

正如出色的评论所指出的那样:

  1. 这不是线程安全的。

  2. 在做这些事情时你应该使用锁。

  3. 可以在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或在其执行期间释放,因此没有其他线程可以获取它和基础执行此方法时,数据结构保持不变。