并行线程 Python GIL 与 Java

3
我知道Python有一个GIL,使得线程无法同时运行,因此线程只是上下文切换。
Java为什么不同呢? 任何语言中的相同CPU上的线程都不能并行运行。
1. 在Java中创建新线程是否利用了多核机器上的核心?
2. Python只能在相同CPU上生成线程,与Java相比如何?
3. 如果是1的情况,即使在Java中使用比CPU更多的线程,对于其中的一些线程也会回到上下文切换吗?
4. 如果是1的情况,那么它与多进程有何不同?因为不能保证利用多个核心?
5. 线程的整个重点不就是能够使用相同的内存空间吗?如果Java确实在多个线程中运行某些线程以进行并行处理,那么它们如何共享内存呢?
谢谢
2个回答

5

Java有什么不同之处?

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


  1. 在Java中创建新线程是否利用了多核计算机的核心?

是的。


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

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

我不确定Python的具体细节,但我认为GIL是一些实现细节而非语言本身的内在特性1。但无论哪种情况,对于Python实现,GIL意味着在多个核上生成线程不会带来太多性能提升。如此页面所述:

"Python全局解释器锁或GIL,简单来说,是一个允许一个线程控制Python解释器的互斥锁(或锁)"


  1. 如果是第一种情况,使用多个线程来超过CPU的数量,Java会回到上下文切换吗?

这取决于情况。在将CPU从属于不同进程的线程之间进行切换时,需要进行完整的上下文切换。但是,在同一进程中在线程之间切换时,只需要切换(用户)寄存器即可。(虚拟内存寄存器和高速缓存不需要切换/刷新,因为线程共享相同的虚拟地址空间。)


  1. 如果1.是正确的,那么它与多处理有何不同?因为利用多个核心并不保证?

多线程和多进程之间的关键区别在于进程不共享任何内存。相比之下,进程中的一个线程可以看到所有其他线程的内存...除了更改何时可见的问题。

这种差异具有各种后果。


  1. 线程化的整个目的不就是能够使用相同的内存空间吗?

是的,这是主要目的...当您将多线程与多进程进行比较时。

如果Java确实在多线程中运行其中一些以进行并行处理...

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

...那么[Java线程]如何共享内存呢?

硬件需要解决让所有线程看到物理内存的问题,并通过内存缓存传播更改。这很复杂。
在Java中,当线程使用共享变量/对象时,责任在程序员身上。你需要使用“volatile”变量或“synchronized”块/方法或其他确保写入和后续读取之间存在“happens before”链的内容。(否则可能会出现不可见的更改问题。)将这种责任转移给程序员允许编译器生成更少的主内存操作的代码......因此更快。缺点是,如果应用程序不遵守规则,则可能以意外的方式运行。
相比之下,在Python中,内存模型未指定,但有一个期望(数百万Python程序员)认为它会按照直觉行事;即由一个线程执行的共享变量写入将立即对其他线程可见。这很难有效地实现,同时还允许Python线程并行运行。
1-虽然GIL没有正式成为Python规范的一部分,但GIL对(未指定!)Python内存模型和Python程序员的假设的影响使其不仅仅是实现细节。 Python是否能成功发展成一种可以有效利用多个核心进行多线程处理的语言仍有待观察。

但我认为GIL实际上是一种实现细节,而不是语言本身固有的东西。这是真的。据说根据语言规范,删除GIL几乎是不可能的,但最近已经有人尝试实现它。点击此处了解更多信息。 - Thomas
我应该写“正在尝试”因为目前还不清楚它(或类似的东西)是否会被合并。 - Thomas
1
是的,其中一个问题是多线程Python程序的内存可见性属性没有明确定义。因此,程序员假定了“显然”的语义;例如,写入将立即对任何线程可见。这在有GIL确保此为真的情况下很好。取走GIL,事情就不会像预期的那样行事。使线程表现良好并保留“预期”的行为并不容易。首先,Python甚至没有正式的内存模型: https://dev59.com/tnA65IYBdhLWcg3w8zft - Stephen C
1
换句话说,GIL实际上已经成为该语言的一个重要特性,尽管它最初并不是旨在成为这样。 - Solomon Slow
1
GIL是瓶颈的原因可以用这句话简单地描述:“Python全局解释器锁或GIL,简单来说,是一个互斥锁(或锁),它只允许一个线程控制Python解释器。” 这意味着一次只能有一个线程执行Python指令。因此...瓶颈。(我不知道你所说的“对象引用机制”是什么。) - Stephen C
显示剩余2条评论

1
这段文字讨论了Python和Java在多线程方面的一些区别。作者指出,Python只能在同一CPU上生成线程,而Java则不然。但这并非本质差异,Python理论上也可以允许操作系统在任何可用的CPU上调度其线程。同时,由于Python线程不能同时执行有意义的工作,如果所有线程都具有相同CPU的亲和性,则潜在地可以提高性能。至于进程控制处理器亲和性是某些操作系统的相对较新的功能,作者不知道任何Python版本是否实际使用该功能。最后,作者回答了Java是否可以运行多个线程以实现并行的问题。
Java不会“运行多个线程以实现并行性”。您的Java程序会因为某些原因创建多个线程,这是由决定的。大多数现代操作系统都提供线程功能。Java只是以一种与语言本身紧密集成的方式向应用程序员提供了这种能力。您可以自由地根据需要使用它们(或不使用它们)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接