Python中的线程安全';词典

Python中的线程安全';词典,python,multithreading,dictionary,thread-safety,Python,Multithreading,Dictionary,Thread Safety,我有一个班上有一本字典 class OrderBook: orders = {'Restaurant1': None, 'Restaurant2': None, 'Restaurant3': None, 'Restaurant4': None} @staticmethod def addOrder(restaurant_name, orders): OrderBook.o

我有一个班上有一本字典

class OrderBook:
    orders = {'Restaurant1': None,
              'Restaurant2': None,
              'Restaurant3': None,
              'Restaurant4': None}

    @staticmethod
    def addOrder(restaurant_name, orders):
        OrderBook.orders[restaurant_name] = orders
我正在运行4个线程(每个餐厅一个)来调用方法
OrderBook.addOrder
。以下是每个线程运行的函数:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)

这是安全的,还是在调用
addOrder
之前必须使用锁?

是的,内置类型本质上是线程安全的:

这简化了CPython实现,使对象模型(包括关键的内置类型,如dict)对并发访问隐式安全


Python的内置结构对于单个操作来说是线程安全的,但有时很难看到一条语句真正变成了多个操作


你的代码应该是安全的。请记住:这里的锁几乎不会增加任何开销,并且会让您安心


有更多细节。

谷歌的风格指南建议不要依赖dict原子性

详情请参阅:

不要依赖内置类型的原子性

虽然Python的内置数据类型(如字典)似乎具有原子操作,但在某些情况下它们不是原子的(例如,如果
\uuuuu hash\uuuuu
\uuuuuu eq\uuu
被实现为Python方法),它们的原子性不应受到依赖。您也不应该依赖于原子变量赋值(因为这反过来又依赖于字典)

使用
队列
模块的队列数据类型作为线程之间通信数据的首选方式。否则,请使用线程模块及其锁定原语。了解如何正确使用条件变量,以便可以使用
线程化.condition
而不是使用较低级别的锁


我同意这一点:CPython中已经有了GIL,所以使用锁对性能的影响可以忽略不计。更昂贵的是,当这些CPython实现细节有一天发生变化时,在复杂的代码库中花上数小时寻找bug。

当使用python的内置dict时,set和get是原子的(因为 然而,这似乎是一种不好的做法,因为像.items这样的操作不是原子的


注意-如果多个线程在同一个dict键上工作,则get-add-set操作不是线程安全的。

当每个线程都写入不同的键时,怎么会出现问题。@Jochen:根据dict的实现方式,可能会出现很多错误。这是一个非常合理的问题。这不是Python的特性,而是cpython的特性。没错,但据我所知,Jython和IronPython中的内置程序即使不使用GIL,也是线程安全的(如果出现unladen swallow,建议也取消GIL)。我假设他没有指定他正在使用的解释程序,他是用Cython来解释的。在Jython的情况下是正确的:这里是Effo.Org。为什么/HOTO to on应该考虑单个操作与复合操作,比如GET-AD-SET。问题是,当我经常读/写DICT时,这种心态的平静会花费我很多。“此处的锁几乎不会增加开销”:为什么?链接已断开,请参见此处: