Python、Ruby、Haskell - 它们提供真正的多线程吗?
我们计划用一些高级编程语言来写一个高并发的应用程序。
1) Python、Ruby 或 Haskell 这些语言支持真正的多线程吗?
2) 如果一个程序里有线程,虚拟机会自动把工作分配到多个核心上吗(或者如果主板上有多个物理 CPU 的话)?
真正的多线程 = 多个独立的执行线程利用多个核心提供的资源(而不是只用一个核心)。
伪多线程 = 线程模拟多线程环境,但不依赖任何操作系统的原生功能。
8 个回答
如果你在编译程序时使用了 -threaded
这个选项,GHC 编译器就会让你的程序在多个操作系统线程上运行,也就是可以同时使用多个核心。然后在运行程序的时候,你需要加上 +RTS -N<x> -RTS
这个参数,其中 <x>
是你想要使用的线程数量。
Haskell的实现版本GHC支持多种在共享内存多核处理器上并行执行的方式。这些方式在“多核Haskell的运行时支持”中有详细介绍。
具体来说,Haskell的运行时会把工作分配给N个操作系统线程,这些线程会分布在可用的计算核心上。这N个操作系统线程又会运行M个轻量级的Haskell线程(有时候可能会有数百万个)。每个Haskell线程可以从一个叫做“火花队列”的地方获取工作(这个队列里可能有数十亿个火花)。就像这样:

运行时会安排工作在不同的核心上执行,还会迁移工作和进行负载均衡。垃圾回收器也是并行的,它会利用每个核心来收集一部分内存。
与Python或Ruby不同,Haskell没有全局解释器锁,因此在多核处理上,GHC表现得特别好,比如在多核性能对比中,Haskell与Python的比较。
1) Python、Ruby 或 Haskell 支持真正的多线程吗?
这个问题跟编程语言本身没关系,主要是看硬件(如果机器只有一个 CPU,那就不可能同时执行两条指令),操作系统(如果操作系统不支持真正的多线程,那也没办法)以及语言的实现和执行引擎。
只要语言规范没有明确禁止或强制要求真正的多线程,这个问题就和语言本身无关。
你提到的所有语言,以及到目前为止回答中提到的所有语言,都有多种实现方式,其中一些支持真正的多线程,有些则不支持,还有一些是基于其他执行引擎的,这些引擎可能支持也可能不支持真正的多线程。
以 Ruby 为例,这里列出一些它的实现和它们的线程模型:
- MRI:绿色线程,不支持真正的多线程
- YARV:操作系统线程,不支持真正的多线程
- Rubinius:操作系统线程,支持真正的多线程
- MacRuby:操作系统线程,支持真正的多线程
- JRuby、XRuby:JVM 线程,取决于 JVM(如果 JVM 支持真正的多线程,那么 JRuby/XRuby 也支持;如果不支持,那它们也无能为力)
- IronRuby、Ruby.NET:和 JRuby、XRuby 类似,但在 CLI 上运行,而不是在 JVM 上
你可以查看我对 Ruby 相关问题的另一个回答(注意那是超过一年前的回答,有些内容可能不再准确。例如,Rubinius 现在使用真正的本地线程,而不是之前的绿色线程。此外,自那以后,出现了几种新的 Ruby 实现,比如 BlueRuby、tinyrb、Ruby Go Lightly、Red Sun 和 SmallRuby)。
Python 的情况类似:
- CPython:本地线程,不支持真正的多线程
- PyPy:本地线程,取决于执行引擎(PyPy 可以本地运行,也可以在 JVM、CLI 或其他 Python 执行引擎上运行。只要底层平台支持真正的多线程,PyPy 也支持)
- Unladen Swallow:本地线程,目前不支持真正的多线程,但计划修复
- Jython:JVM 线程,参考 JRuby
- IronPython:CLI 线程,参考 IronRuby
对于 Haskell,至少 Glorious Glasgow Haskell Compiler 支持使用本地线程的真正多线程。我对 UHC、LHC、JHC、YHC、HUGS 或其他实现不太了解。
对于 Erlang,BEAM 和 HiPE 都支持使用绿色线程的真正多线程。
2) 如果一个程序包含线程,虚拟机会自动将工作分配到多个核心(或者如果主板上有多个 CPU,就分配到物理 CPU)吗?
这同样取决于虚拟机、操作系统和硬件。此外,上面提到的一些实现甚至没有虚拟机。