【问题标题】:Python GIL and globalsPython GIL 和全局变量
【发布时间】:2010-01-28 19:13:13
【问题描述】:

在 python 中,我定义了一个由不同线程读取/递增的全局变量。由于 GIL,如果不使用任何类型的锁定机制,这是否会导致问题?

【问题讨论】:

标签: python gil


【解决方案1】:

GIL 只要求解释器在另一个线程接管之前完全执行单个字节码指令。但是,没有理由假设递增操作是单条指令。例如:

>>> import dis
>>> dis.dis(compile("x=753","","exec"))
  1           0 LOAD_CONST               0 (753)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE
>>> dis.dis(compile("x+=1","","exec"))
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (1)
              6 INPLACE_ADD
              7 STORE_NAME               0 (x)
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

如您所见,即使是这些简单的操作也不仅仅是一条字节码指令。因此,每当在线程之间共享数据时,您必须使用单独的锁定机制(例如 threading.lock)以保持数据一致性。

【讨论】:

  • 哎哟。我的意思是,3 个赞成票,没有人注意到 dis.dis("x=753") 输出?我更正了代码。
  • 这是一个例子,我应该更加注意我正在写的内容 - 谢谢:)。此外,它更清楚地显示了点 - 加载值后,在再次存储值之前有 几个 指令。
  • 这甚至不是 100% 正确的。字节码(几乎所有)实际上可以通过__getitem____add__ 或任何其他场景调用更多的python 代码。然后你最终会在一个字节码中途交换线程。
【解决方案2】:

是的,没有锁定的多线程几乎总是会导致问题,不管有没有 GIL。

【讨论】:

  • 请注意,GIL 不是用来保护您的应用程序数据的;它只是为了保护一些 Python 内部结构,例如 Python 对象的引用计数。你仍然需要锁定你的结构。
  • 没错。 GIL 保护 Python 免受自身的影响,但它没有做任何事情来保护你。
  • 当然,绝大多数 Python 执行引擎甚至没有 GIL。
猜你喜欢
  • 1970-01-01
  • 2018-10-26
  • 2019-07-24
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多