8

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

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

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

4

3 回答 3

6

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。不幸的是,幻灯片已离线,但视频应该仍然有效。

于 2011-08-04T17:03:01.250 回答
4

无锁编程在 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 实现者之一)在 Haskell 中讨论多核编程的幻灯片。

于 2011-08-04T17:30:52.770 回答
2

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

于 2011-08-04T16:49:42.913 回答