为什么 Java 虚拟机中没有 GIL? 为什么 Python 那么需要 GIL?

我希望有人能够提供一些关于 Java 虚拟机本质上的不同之处的见解。 Java 虚拟机允许它在不需要 GIL (gIL)的情况下很好地实现线程,而 Python 则需要这样一个邪恶的东西。

19680 次浏览

Python (该语言)不需要 GIL (这就是为什么它可以完美地在 JVM [ Jython ]和。NET [ IronPython ] ,以及那些实现可以免费使用多线程)。CPython (流行的实现)总是使用 GIL 来简化编码(尤其是。垃圾收集机制的编码)和非线程安全的 C 编码库的集成(过去有很多这样的库; ——)。

除了其他雄心勃勃的目标之外,卸货燕子项目为 Python 提供了一个 计划无 GIL 的虚拟机——引用该站点的话,“此外,我们打算删除 GIL 并修复 Python 中的多线程状态。我们相信,通过实现更复杂的 GC 系统,比如 IBM 的回收器(Bacon et al,2001) ,这是可能的。”

JVM (至少是热点)确实有一个类似于“ GIL”的概念,只是它的锁粒度要细得多,其中大部分来自于更高级的 GC 热点。

在 CPython 中,它是一个大锁(可能不是那么正确,但是对于参数来说已经足够好了) ,在 JVM 中,根据使用它的位置,它更多地使用不同的概念。

例如,看看热点代码中的 vm/run/safepoint.hpp,它实际上是一个障碍。一旦到达安全点,整个虚拟机就会停止使用 Java 代码,就像 pythonVM 停在 GIL 处一样。

在 Java 世界中,这样的 VM 暂停事件被称为“ stop-the-world”,在这些点上,只有绑定到某些条件的本机代码可以自由运行,其余的 VM 已经停止。

Java 中缺乏粗锁也使 JNI 更难编写,因为 JVM 对 FFI 调用的环境保证较少,这是 cpython 相当容易做到的事情之一(尽管不像使用 ctype 那么容易)。

在这篇博客文章 http://www.grouplens.org/node/244的下面有一个评论,它暗示了为什么在 IronPython 或 Jython 中很容易省略 GIL 的原因,这是因为 CPython 使用引用计数,而其他2个虚拟机有垃圾收集器。

我不明白为什么会这样,但听起来确实是个合理的理由。

Python 缺少 jit/aot,在多线程处理器上编写它的时间框架也不存在。或者,您可以在缺乏 GIL 的 Julia lang 中重新编译所有内容,从而提高 Python 代码的速度。而且 Jython 有点糟糕,它比 Cpython 和 Java 慢。如果你想坚持使用 Python,考虑使用并行插件,你不会立即获得速度提升,但你可以使用正确的插件进行并行编程。

链接中,他们有以下解释:

...”部分解释器不是线程安全的,尽管主要是因为通过大量使用锁使它们都是线程安全的,这将极大地降低单线程的速度(来源)。这似乎与使用引用计数的 CPython 垃圾收集器有关(JVM 和 CLR 不需要,因此不需要每次都锁定/释放引用计数)。但即使有人想出了一个可接受的解决方案并加以实施,第三方库仍然会面临同样的问题。”