Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading forkIO线程和OS线程_Multithreading_Haskell - Fatal编程技术网

Multithreading forkIO线程和OS线程

Multithreading forkIO线程和OS线程,multithreading,haskell,Multithreading,Haskell,如果我使用forkIO创建线程,我需要提供一个函数来运行并获取标识符(threadID)。然后,我可以通过工作负载、MVAR等与该动物进行通信。。然而,据我所知,创建的线程非常有限,只能以SIMD方式工作,其中为线程创建提供的函数是指令。我无法更改线程启动时提供的函数。我知道这些用户线程最终是由OS映射到OS线程的 我想知道Haskell线程和OS线程是如何实现接口的。为什么可以将做完全不同事情的Haskell线程映射到同一个OS线程?为什么不需要用固定的指令启动操作系统线程(正如在forkIO

如果我使用forkIO创建线程,我需要提供一个函数来运行并获取标识符(threadID)。然后,我可以通过工作负载、MVAR等与该动物进行通信。。然而,据我所知,创建的线程非常有限,只能以SIMD方式工作,其中为线程创建提供的函数是指令。我无法更改线程启动时提供的函数。我知道这些用户线程最终是由OS映射到OS线程的

我想知道Haskell线程和OS线程是如何实现接口的。为什么可以将做完全不同事情的Haskell线程映射到同一个OS线程?为什么不需要用固定的指令启动操作系统线程(正如在forkIO中所需要的那样)?调度器(?)如何识别应用程序中可能分布的用户线程?换句话说,为什么操作系统线程如此灵活


最后,是否有任何方法可以从应用程序中转储所选线程的堆?

首先,让我们解决一个简单的误解:

我知道这些用户线程最终是由OS映射到OS线程的

实际上,Haskell运行时负责从其池中选择特定OS线程正在执行的Haskell线程

现在是问题,一次一个

为什么可以将做完全不同事情的Haskell线程映射到同一个OS线程

暂时忽略FFI,所有OS线程实际上都在运行Haskell运行时,该运行时跟踪准备就绪的Haskell线程列表。运行时选择一个Haskell线程来执行,并跳入代码,直到该线程将控制权交还给运行时为止。此时,运行时有机会继续执行相同的线程或选择不同的线程

简而言之:许多Haskell线程可以映射到单个OS线程,因为实际上OS线程只做一件事,即运行Haskell运行时

为什么不需要用固定的指令启动操作系统线程(正如在forkIO中所需要的那样)

我不理解这个问题(我认为它源于第二个误解)。使用固定指令启动OS线程的意义与使用固定指令启动Haskell线程的意义完全相同:对于每一件事情,您只需给出一段代码来执行,这就是它所做的

调度器(?)如何识别应用程序中可能分布的用户线程

“分布式”是一个危险的词:通常,它指的是在多台机器上传播代码(可能不是您在这里的意思)。至于Haskell运行时如何判断何时有多个线程,这很简单:当调用
forkIO
时就可以判断

换句话说,为什么操作系统线程如此灵活

我不清楚OS线程是否比Haskell线程更灵活,所以这个问题有点奇怪

最后,有没有办法从应用程序中转储所选线程的堆

实际上,我根本不知道有什么工具可以在多线程应用程序或其他应用程序中转储Haskell堆。如果愿意,您可以使用类似的包转储可从特定对象访问的堆部分的表示。过去,我曾非常成功地想象过这些垃圾场


有关更多信息,您可能会喜欢我的中两部分“约定”和“国外导入”,也可能会喜欢“非线程运行时”部分的一些内容。

我将尝试提供多线程Haskell程序如何实现的概念模型,而不是试图直接回答您的问题。我将忽略许多细节和复杂性

操作系统实现使用以允许多个计算“线程”同时在同一核心上逻辑运行

操作系统提供的线程往往很重。它们非常适合于某些类型的“多线程”应用程序,并且在Linux等系统上,基本上是允许多个程序同时运行的同一工具(它们擅长这项任务)

但是,这些线程对于高级语言(如Haskell)的许多用途来说都有点重。从本质上讲,GHC运行时作为迷你操作系统工作,在操作系统线程之上实现自己的“线程”,就像操作系统在内核之上实现线程一样

从概念上很容易想象像Haskell这样的语言会以这种方式实现。评估Haskell包括“强制thunk”,其中thunk是可能为1的计算单位。取决于另一个值(thunk)和/或2。创建新的thunks

因此,可以想象多个线程同时计算thunk。我们将构造一个待评估的thunk队列。每个线程将弹出队列的顶部,并计算该thunk直到完成,然后从队列中选择一个新thunk。操作
par
及其类似操作可以通过向该队列添加thunk来“触发”新的计算

将此模型扩展到IO操作也不是特别难想象。我们想象Haskell计算的单位会更复杂一些,而不是简单地强制执行纯thunk。Psuedo Haskell用于此类运行时:

type Spark = (ThreadId,Action)
data Action = Compute Thunk | Perform IOAction
注意:这只是为了概念上的理解,不要认为事情是这样实现的

当我们运行Spark时,我们会寻找“抛出”到该线程ID的异常。假设没有异常,执行包括强制thunk或执行IO操作

很明显,我在这里的解释是非常曲折的,忽略了一些复杂性。关于更多信息,GHC团队撰写了优秀的文章,如Marlow等人的“多核Haskell的运行时支持”