并行线程 python GIL 与 Java

Ami*_*aus 3 python java parallel-processing multithreading gil

我知道Python有一个GIL,它使得线程不能同时运行,因此线程只是上下文切换。

为什么java不一样?每种语言的同一 CPU 上的线程不能并行运行。

  1. 在java中创建新线程是否利用多核机器中的核心?

  2. 与 java 相比,python 只能在同一 CPU 上生成线程?

  3. 如果 1. 是这种情况,当使用比 CPU 更多的线程时,即使在 java 中,也会再次返回其中几个线程的上下文切换?

  4. 如果 1. 是这样的话,那么它与多处理有何不同?因为不能保证利用多个核心?

  5. 线程的全部意义不就是能够使用相同的内存空间吗?如果java确实在多个线程中运行其中一些以实现并行性,那么它们如何真正共享内存?

谢谢

Ste*_*n C 6

为什么java不一样?

因为它能够同时有效地使用多个核心。


  1. 在java中创建新线程是否会利用多核机器中的核心?

是的。


  1. 与 Java 相比,Python 只能在同一 CPU 上生成线程?

Java 可以在不同的 CPU 上生成多个线程。Java 不负责实际的线程调度。这是由操作系统处理的。并且操作系统可能会将线程重新调度到与它启动时不同的 CPU。

我不确定 Python 的确切细节,但我认为 GIL 是一个实现细节,而不是语言本身固有的东西1。但无论哪种方式,在 Python 实现中,GIL 都意味着在多个内核上生成线程时几乎不会获得任何性能优势。正如本页所说:

“简单来说,Python 全局解释器锁或 GIL 是一种互斥体(或锁),只允许一个线程控制 Python 解释器。”


  1. 如果1.是这种情况,当使用的线程多于CPU时,它会回到Java中的上下文切换吗?

这取决于。当在属于不同进程的线程之间切换CPU时,涉及完整的上下文切换。但在同一进程中的线程之间切换时,只需要切换(用户)寄存器​​。(虚拟内存寄存器和缓存不需要切换/刷新,因为线程共享相同的虚拟地址空间。)


  1. 如果是这种情况,那么它与多处理有何不同?因为不能保证利用多个核心?

多线程和多处理之间的主要区别在于进程不共享任何内存。相比之下,进程中的一个线程可以看到所有其他线程的内存……何时可见更改的模数问题。

这种差异会产生多种后果。


  1. 线程的全部意义不就是能够使用相同的内存空间吗?

是的,这就是要点……当您将多线程与多处理进行比较时。

如果 Java 确实在多个线程中运行其中一些以实现并行性......

Java 支持线程有很多原因。并行性只是这些原因之一。其他包括复用 I/O 和简化某些类型的编程问题。这些其他原因也与 Python 有关。

...[Java线程]如何真正共享内存?

硬件处理使物理内存对所有线程可见以及通过内存缓存传播更改的问题。这很复杂。


在 Java 中,当线程使用共享变量/对象时,程序员有责任“做正确的事情”。您需要使用volatile变量、块/方法或其他东西来确保写入和后续读取之间synchronized存在发生之前链。(否则您可能会遇到更改不可见的问题。)

这种将责任转移给程序员的做法使得编译器可以用更少的主内存操作生成代码……因此速度更快。缺点是,如果应用程序不遵守规则,它可能会出现意想不到的行为。

相比之下,Python 中的内存模型是未指定的,但(数以百万计的 Python 程序员)期望它会以直观的方式运行;即一个线程执行的共享变量写入将立即对其他线程可见。这很难高效地实现,同时又允许 Python 线程并行运行。


1 - 虽然 GIL 并不是 Python 规范的正式组成部分,但 GIL 对(未指定!)Python 内存模型和 Python 程序员假设的影响使其不仅仅是一个实现细节。Python 能否成功演变成多线程可以有效利用多个核心的语言还有待观察。