【问题标题】:Can you race condition in Python while there is a GIL?当有 GIL 时,你可以在 Python 中竞争条件吗?
【发布时间】:2014-05-25 12:12:07
【问题描述】:

我的理解是,由于 cPython 中的全局解释器锁,任何时候都只能执行一个线程。这是否会自动防止竞争条件(例如丢失更新问题)?

为了清楚起见,我是从理论的角度来问的。如果没有同步,我永远不会编写线程代码。

【问题讨论】:

  • 只有一个线程可以执行python字节码。你不应该依赖这个并假设竞争条件是不可能的。
  • 所以你仍然可以有一个线程交错,这会导致更新丢失?
  • 当然。执行 python 指令的 2 个线程不会在不同的内核上同时执行(这就是为什么线程通常不会提高性能的原因),但它不像解释器选择一个线程来运行,直到它在执行下一个线程之前退出。那将是……疯狂。
  • 虽然问题暗示与线程相关的竞争条件是讨论的范围,但它并没有在任何地方真正说明。显然,GIL 对进程间竞争条件(在不同 CPU 上运行的相同代码的两个实例等)完全没有帮助。

标签: python race-condition gil


【解决方案1】:

由于 GIL,每个进程只有一个线程来执行 Python 字节码;字节码评估循环受它保护。

锁每sys.getswitchinterval() 秒释放一次,此时可以进行线程切换。这意味着对于 Python 代码,线程切换仍然可以发生,但仅限于字节码指令之间。任何依赖线程安全的代码都需要考虑到这一点。可以在一个字节码中完成的操作可以是线程安全的,其他的都不是。

即使是单个字节码指令也可以触发其他 Python 代码;例如,object[index] 行可以触发对自定义类的__getitem__ 调用,该类在 Python 中实现。因此,单个BINARY_SUBSCR 操作码不一定是线程安全的,具体取决于对象类型。

【讨论】:

  • 很好的答案。我只想提一下,在我目前使用的 3.9.5 中,sys.getcheckinterval() 被替换为 sys.getswitchinterval()
  • @SorousHBakhtiary:谢谢你戳我; getswitchinterval() 是在 Python 3.2 中引入的,随着 Python 2 早已不复存在,现在是时候更新这个答案了。
猜你喜欢
  • 2022-11-10
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多