Haskell中的并发编程
与Java/Scala相比,关于Haskell中并发编程的两个(相关)问题:Haskell中的并发编程,haskell,concurrency,jvm,ghc,Haskell,Concurrency,Jvm,Ghc,与Java/Scala相比,关于Haskell中并发编程的两个(相关)问题: Haskeller对并发数据结构有什么用途?有什么类似于Java的Java.util.concurrent.{ConcurrentHashMap,ConcurrentSkipListSet,…}MVar(映射k v)不计算:)。共享可变状态是邪恶的,但有时是必要的 是否有与Java的ExecutorService等价的服务?AFAIK、Haskell线程(参见GHC.Exts中的fork、yield等)都是通过RTS中
Java.util.concurrent.{ConcurrentHashMap,ConcurrentSkipListSet,…}
<代码>MVar(映射k v)不计算:)。共享可变状态是邪恶的,但有时是必要的ExecutorService
等价的服务?AFAIK、Haskell线程(参见GHC.Exts
中的fork
、yield
等)都是通过RTS中内置的某种方式进行调度的。但如果我特别想使用fork-join池,或者在线程池上安排一些计算,该怎么办?在Scala中,能够将未来的放在特定的执行上下文中非常方便,我不知道在Haskell中如何做到这一点关于这个话题可以写一整本书,所以我将试着谈谈你所问的问题
- 您可以使用
combinator来安排在将来某个时间点进行的纯计算。RTS已经为此实现了工作窃取队列,并且已经为每个CPU核心维护了一个线程来运行它们。(如果您使用适当的开关链接您的程序。)请注意,这对不纯净代码没有任何帮助,并且不允许您指定代码在哪个线程或哪个内核上执行par
- 对于共享可变存储,您有两种选择
- 使用
显式锁定。在其他编程语言中,这具有锁定的所有常见缺陷。(死锁,忘记锁东西,锁的东西太多,锁的时间太长,锁的时间不够长…)所以MVar
绝对重要MVar(mapkv)
- STM。你似乎误解了它的作用。STM的全部要点是不需要锁。它允许您使用共享的可变数据结构,就好像它们不是共享的一样,但它会自动防止数据争用、状态不一致以及所有其他不使用锁的常见问题。它还允许线程同时在多个条件下等待。这是一个令人难以置信的框架
- 使用
- 如果您想在特定的操作系统线程上运行代码,您可能正在寻找
,而不是forkOS
forkIO
考虑到您的用例,我怀疑STM可能就是您所寻找的。如果你有一个具体的任务要做,再发一个问题,你可能会得到更具体的建议。为什么
MVar(Map k v)
不算数?你错过了什么功能?@chiMVar(mapkv)
完全阻止并发访问。类似于ConcurrentHashMap
的东西只会锁定映射的子集。@jberryman我有点希望GHC附带的库中有某种东西可以在各种工作窃取方案上提供一个抽象层(就像Java标准库中的情况一样)。听起来2的答案很简单,“不在任何引导库中,但可能在Hackage上”。这是一个非常广泛的问题,因此需要尝试回答。我建议您阅读Simon Marlow的免费书籍《据我所知@Alec》,STM只是在并发上下文中工作的一个有用的抽象,提供了比例如MVar
更好的属性(请参见包描述),那么您为什么不希望您的结构的操作存在于此呢?您可以原子地传输:STM a->IO a
。如果需要,还可以在IO
中获取结构,请参见例如newIO::IO(映射键值)
。同意ctrie
但它可能非常有用。par
被(非官方地)弃用,取而代之的是parEval
(或者在Control.Parallel.Strategies
中实现更原始但性能较差的rpar
)par
在控制推测计算方面存在问题,因为没有明确的方法告诉系统您是否仍打算使用推测计算的结果(我认为可能也存在GC问题)。Marlow似乎认为整个内置并行机制有点难以控制。现在他更喜欢Par
monad。共享并发存储还有另一种机制:对IORef
和各种数组类型的原子操作。这些操作有利于编写无锁结构,这有时是合适的。