【问题标题】:Lock-free programming in HaskellHaskell 中的无锁编程
【发布时间】:2011-08-04 16:44:00
【问题描述】:

有谁知道是否可以在 Haskell 中进行无锁编程?我感兴趣的问题是适当的低级原语是否可用,以及(如果有的话)关于在纯功能上下文中使用这些原语构建工作的大规模系统的任何信息。 (我以前从未在纯函数上下文中进行过无锁编程。)例如,据我了解,Control.Concurrent.Chan 通道是建立在 MVar 之上的,它(据我所知)使用锁—— -原则上可以构建内部无锁的Chan原语版本吗?希望获得多少性能提升?

我还应该说我熟悉 TVar 的存在,但了解它们的内部实现 --- 我已经了解它们大多是无锁的,但我不确定它们是否完全无锁。因此,任何有关 TVar 内部实现的信息也会有所帮助!

This thread 提供了一些讨论,但我想知道是否有任何更新/更全面的内容。)

【问题讨论】:

    标签: haskell lock-free


    【解决方案1】:

    MVar 不仅使用锁,它锁抽象。而且,我记得,个别 STM 原语是乐观的,但在 STM 实现的各个地方都使用了锁。只记得方便的押韵:“如果它可以阻塞,那么当心锁”。

    对于真正的无锁编程,您希望直接使用 IORefs 以及 atomicModifyIORef

    编辑:关于黑洞,我记得实现是无锁的,但我不能保证细节。该机制在“多核 Haskell 的运行时支持”中进行了描述:http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel/multicore-ghc.pdf

    但我认为,该实现经历了一些调整,正如 Simon Marlow 的 2010 Haskell 实现者研讨会演讲“调度多核延迟评估”中所述:http://haskell.org/haskellwiki/HaskellImplementorsWorkshop/2010。很遗憾,幻灯片已离线,但视频应该仍然可以播放。

    【讨论】:

    • 我的印象是,如果有的话,STM 往往会在另一个极端失败——高争用且没有锁定,无限乐观导致交易愉快地左右无效,直到没人能得到什么都做了。
    • 对!我同意,MVar 只是简单的锁;这个问题的措辞不够理想。我同意我想使用 IORefs 和原子修改。但是atomicModifyIORef 并不是您可能想要的唯一无锁原语——关键的是,人们可能想要一个compare-and-set! 原语,它仅在其当前值仍然是您期望的值时修改 IORef...
    • 还有:黑洞机制是用锁实现的吗? (在 GHC 中。)
    • 是的,据我所知没有比较和交换。但是 thunk 延迟语义应该足以通过atomicModifyIORef 为您提供所需的任何东西。当然,不利的一面是,作为交换,您需要支付惰性垃圾收集语言的典型常量因子开销。
    • 不需要和 atomicModifyIORef 进行比较和交换,你只需要在你用来进行修改的函数中,你比较的是你想要的,如果是的话,交换它,如果不是,则将原始值保留在那里。你可以在你的函数中做任何你想做的事情,不管它有多复杂,因为 atomicModifyIORef 所做的只是在其自身内部放置一个 thunk 以供计算,将来可以由需要它的线程进行评估。有关详细信息,请参阅我对问题的回复和引用的幻灯片。
    【解决方案2】:

    无锁编程在 Haskell 中是微不足道的。拥有需要由多个线程修改的共享数据的最简单方法是从任何普通的 haskell 类型(列表、映射、可能,任何您需要的)开始,并将其放在 IORef 中。完成此操作后,您就可以使用 atomicModifyIORef 就地执行修改,保证几乎不需要任何时间。

    type MyDataStructure = [Int]
    type ConcMyData = IORef MyDataStructure
    
    main = do
        sharedData <- newIORef []
        ...
        atomicModifyIORef sharedData (\xs -> (1:xs,()))
    

    这样做的原因是存储了指向最终将评估 IORef 内部结果的 think 的指针,并且每当线程从 IORef 读取时,它们都会获得 thunk,并根据需要评估尽可能多的结构.由于所有线程都可以读取相同的 thunk,因此它只会被评估一次(如果它被多次评估,则保证总是以相同的结果结束,所以并发评估是可以的)。我相信这是正确的,不过我很高兴得到纠正。

    由此得出的结论是,这种抽象只能在纯语言中轻松实现,其中事物的价值永远不会改变(当然,当它们改变时,IORef、MVars 和 STM 类型等类型除外) )。 Haskell 数据结构的写入时复制特性意味着修改后的结构可以与原始结构共享大量数据,同时只分配结构中的任何新数据。

    我认为我没有很好地解释这是如何工作的,但我明天会回来澄清我的答案。

    有关详细信息,请参阅 Microsoft Research 的 Simon Marlow(也是 GHC 的主要实施者之一)的演讲 Multicore programming in Haskell 的幻灯片。

    【讨论】:

      【解决方案3】:

      查看stm,特别是它的 TChan 类型。

      【讨论】:

      • 谢谢---我知道 STM(见上面的编辑),但不太了解它是如何在内部实现的。是无锁的吗?大多是无锁的?此外,是否暴露了任何较低级别的无锁原语?
      • @circular-ruin 我很确定 STM 是无锁的,但如果不是,它是你将得到的最好的。
      • 好的,很公平!虽然如果有人有更详细的信息(或者可以指出这样的......),我仍然很感兴趣
      • STM 很乐观,但我记得不是完全无锁。
      • 我也同意 STM 不是无锁的。它让您在无锁庄园中思考,但它更多的是对几乎可以肯定必须在某处使用锁定的东西的抽象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 2017-07-16
      相关资源
      最近更新 更多