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/Scala相比,关于Haskell中并发编程的两个(相关)问题:

  • Haskeller对并发数据结构有什么用途?有什么类似于Java的
    Java.util.concurrent.{ConcurrentHashMap,ConcurrentSkipListSet,…}
    <代码>MVar(映射k v)不计算:)。共享可变状态是邪恶的,但有时是必要的

  • 是否有与Java的
    ExecutorService
    等价的服务?AFAIK、Haskell线程(参见
    GHC.Exts
    中的
    fork
    yield
    等)都是通过RTS中内置的某种方式进行调度的。但如果我特别想使用fork-join池,或者在线程池上安排一些计算,该怎么办?在Scala中,能够将未来的放在特定的执行上下文中非常方便,我不知道在Haskell中如何做到这一点


  • 关于这个话题可以写一整本书,所以我将试着谈谈你所问的问题

    • 您可以使用
      par
      combinator来安排在将来某个时间点进行的纯计算。RTS已经为此实现了工作窃取队列,并且已经为每个CPU核心维护了一个线程来运行它们。(如果您使用适当的开关链接您的程序。)请注意,这对不纯净代码没有任何帮助,并且不允许您指定代码在哪个线程或哪个内核上执行

    • 对于共享可变存储,您有两种选择

      • 使用
        MVar
        显式锁定。在其他编程语言中,这具有锁定的所有常见缺陷。(死锁,忘记锁东西,锁的东西太多,锁的时间太长,锁的时间不够长…)所以
        MVar(mapkv)
        绝对重要

      • STM。你似乎误解了它的作用。STM的全部要点是不需要锁。它允许您使用共享的可变数据结构,就好像它们不是共享的一样,但它会自动防止数据争用、状态不一致以及所有其他不使用锁的常见问题。它还允许线程同时在多个条件下等待。这是一个令人难以置信的框架

    • 如果您想在特定的操作系统线程上运行代码,您可能正在寻找
      forkOS
      ,而不是
      forkIO


    考虑到您的用例,我怀疑STM可能就是您所寻找的。如果你有一个具体的任务要做,再发一个问题,你可能会得到更具体的建议。

    为什么
    MVar(Map k v)
    不算数?你错过了什么功能?@chi
    MVar(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
    和各种数组类型的原子操作。这些操作有利于编写无锁结构,这有时是合适的。