与其试图直接回答您的问题,我会尝试为多线程Haskell程序的实现提供一个概念模型。我会忽略许多细节和复杂性。
操作系统执行preemptive multithreading使用hardware interrupts允许计算的多个“线程”在逻辑上同时运行在同一个内核上。
操作系统提供的线程往往是重量级的。它们非常适合某些类型的“多线程”应用程序,并且在像Linux这样的系统上,它们基本上是同一个工具,允许多个程序同时运行(他们擅长的任务)。
但是,这些线程对于Haskell等高级语言的许多用途来说有点重量。从本质上讲,GHC运行时作为小型操作系统,在操作系统线程之上实现自己的“线程”,就像操作系统在内核之上实现线程一样。
从概念上很容易想象像Haskell这样的语言将以这种方式实现。评估Haskell包含“强制thunk”,其中thunk是一个计算单位,可能依赖于另一个值(thunk)和/或2.创建新thunk。
因此,可以想象多个线程同时评估thunk。人们会构建一个被评估的thunk队列。每个线程将弹出队列的顶部,并评估该thunk直到完成,然后从队列中选择一个新的thunk。操作par
及其同类可以通过向该队列添加一个thunk来“激发”新的计算。
将此模型扩展到IO操作并不是特别难以想象。我们认为Haskell计算的单位稍微复杂一些,而不是简单地强制纯粹的thunk。伪哈斯克尔这种运行时:
type Spark = (ThreadId,Action)
data Action = Compute Thunk | Perform IOAction
注意:这仅仅是为了概念上的理解,不要以为事情以这种方式实现
当我们运行一个火花,我们期待为例外“扔”到该线程ID。假设我们没有,执行包括强制执行thunk或执行IO操作。
显然,我在这里的解释一直很手动,并且忽略了一些复杂性。有关更多信息,GHC团队撰写了优秀的文章,例如Marlow等人的“多核Haskell运行时支持”。您可能还想看看操作系统上的教科书,因为他们经常深入了解如何构建调度程序。
您可能有兴趣阅读http://community.haskell.org/~simonmar/papers/conc-ffi.pdf,它很好地解释了多线程Haskell的实现。这有点旧,但仍然非常重要。尽管有这个头衔,但它远远超过FFI。 –