[英]Do IO operations run in green threads?
给出Control.Concurrent.Async中的示例:
do a1 <- async (getURL url1)
a2 <- async (getURL url2)
page1 <- wait a1
page2 <- wait a2
两个getURL
调用是在不同的OS线程上运行,还是只是在不同的绿色线程上运行?
如果我的问题没有意义...说程序只在一个OS线程上运行,这些调用是否仍然会同时进行? 阻塞IO操作是否阻止整个操作系统线程和该操作系统线程上的所有绿色线程,或只阻止一个绿色线程?
此模块提供一组操作,用于异步运行IO操作并等待其结果。 它是Control.Concurrent提供的基本并发操作的薄层。
Haskell线程的调度在Haskell运行时系统内部完成,并且不使用任何操作系统提供的线程包。
如果不仔细解释,这最后可能会有点误导:尽管Haskell线程的调度 - 即选择下一个运行的Haskell代码 - 是在不使用任何OS工具的情况下完成的,但GHC可以并确实使用多个OS线程实际执行任何选择运行的代码,至少在使用线程运行时系统时。
它应该都是绿色线程。
如果您的程序是使用单线程RTS编译(或者更确切地说是链接)的,那么所有绿色线程都在单个OS线程中运行。 如果您的程序是使用多线程RTS编译(链接)的,则每个CPU核心调度一些任意数量的绿色线程(默认情况下)一个OS线程。
据我所知,在任何一种情况下,阻塞I / O调用应该只阻止一个绿色线程。 其他绿色线程应完全不受影响。
这并不像问题似乎暗示的那么简单。 Haskell是一种比大多数人遇到的更强大的编程语言。 特别是, IO
,似乎从一个角度内部点块可以被实现为顺序操作的“开始非阻塞IO操作,暂停线,等待IO操作在覆盖多个Haskell的螺纹的IO管理器来完成的,队列IO设备准备就绪后恢复的线程。“
请参阅waitRead#和waitWrite#以获取与标准全局IO管理器一起提供该功能的api。
是否使用绿色线程与此模式无关。 可以编写IO操作以在后台使用非阻塞IO,并使用适当的多路复用,同时显示为其用户提供阻塞接口。
不幸的是,它也不是那么简单。 事实是操作系统的限制受到阻碍。 直到最近(我认为5.1内核昨天发布,也许?),Linux没有为非阻塞磁盘操作提供良好的接口。 当然有些事情看起来应该有效,但在实践中它们并不是很好。 因此,磁盘读/写是GHC中的实际阻塞操作。 (不仅仅是在Linux上.GHC没有很多开发人员支持它,所以很多东西都是用在linux上运行的相同代码编写的,即使还有其他选择。)
但它甚至不像“网络操作隐藏无阻塞,磁盘操作阻塞”那么简单。 至少可能不是。 我实际上并不知道,因为在非线程运行时上找到文档很难。 我知道线程运行时实际上维护了一个单独的线程池,用于执行标记为“安全”的FFI调用,这可以防止它们阻止执行绿色线程。 我不知道非线程运行时是否也是如此。
但是对于你的例子,我可以说 - 假设getURL
使用标准网络库(无论如何它是一个假设的函数),它将在后台进行适当的多路复用的非阻塞IO。 因此,即使没有线程运行时,这些操作也将是真正的并发。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.