Python字典中的线程安全

nma*_*mat 92 python multithreading dictionary thread-safety

我有一个持有字典的班级

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

    @staticmethod
    def addOrder(restaurant_name, orders):
        OrderBook.orders[restaurant_name] = orders
Run Code Online (Sandbox Code Playgroud)

我正在运行调用该方法的4个线程(每个餐厅一个)OrderBook.addOrder.这是每个线程运行的函数:

def addOrders(restaurant_name):

    #creates orders
    ...

    OrderBook.addOrder(restaurant_name, orders)
Run Code Online (Sandbox Code Playgroud)

这是安全的,还是我必须在打电话前使用锁addOrder

Ned*_*der 83

Python的内置结构对于单个操作是线程安全的,但有时很难看到语句真正成为多个操作的位置.

您的代码应该是安全的.请记住:这里的锁定几乎不会增加任何开销,让您高枕无忧.

http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm 有更多详细信息.

  • 这是effbot.org [实施锁定]的原因/方法(http://effbot.org/zone/thread-synchronization.htm) (5认同)
  • 问题是,当我经常读/写那个词时,那种安心会让我付出很多代价. (5认同)
  • “这里的锁几乎不会增加任何开销”:为什么呢? (4认同)
  • 该链接已失效,请参见此处:https://titanwolf.org/Network/Articles/Article?AID=41de1eb2-63d6-48f3-90a7-914940fbae81#gsc.tab=0 (2认同)

小智 28

是的,内置类型本质上是线程安全的:http: //docs.python.org/glossary.html#term-global-interpreter-lock

这通过使对象模型(包括诸如dict的关键内置类型)对于并发访问而言是隐式安全的,从而简化了CPython实现.

  • 这不是Python的功能,而是*cpython*的功能. (19认同)
  • 没错,但据我所知,Jython和IronPython中的内置函数也是线程安全的,即使没有使用GIL(和unladen swallow,如果它出现,也建议取消GIL).我认为,因为他没有指定他正在使用的翻译,所以他的意思是CPython. (8认同)
  • 在 Jython 的情况下正确:http://www.jython.org/jythonbook/en/1.0/Concurrency.html#java-or-python-apis (3认同)

Cir*_*四事件 21

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

更详细的解释在:Python 变量赋值是原子的吗?

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

While Python’s built-in data types such as dictionaries appear to have atomic operations, there are corner cases where they aren’t atomic (e.g. if __hash__ or __eq__ are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries).

Use the Queue module's Queue data type as the preferred way to communicate data between threads. Otherwise, use the threading module and its locking primitives. Learn about the proper use of condition variables so you can use threading.Condition instead of using lower-level locks.

And I agree with this one: there is already the GIL in CPython, so the performance hit of using a Lock will be negligible. Much more costly will be the hours spent bug hunting in a complex codebase when those CPython implementation details change one day.