【问题标题】:Are purely functional data structures always lock-free?纯函数式数据结构总是无锁的吗?
【发布时间】:2014-04-16 17:05:41
【问题描述】:

我在多个地方都看到过这种说法,包括在 SO:https://stackoverflow.com/a/20467457/243238https://stackoverflow.com/a/4400389/243238。我的意思是修改数据不需要锁,但在并发修改后你最终会得到它的多个版本。这在实践中似乎不是很有用。我试图用下面的一个简单场景来描述这一点:

假设我们有 2 个线程 A 和 B。它们都在修改纯函数字典 D。此时它们不需要锁,因为数据是不可变的,因此它们输出新的字典 DA 和 DB。现在我的问题是如何协调 DA 和 DB,以便以后的操作可以看到数据的单一视图?

编辑:答案建议在 DA 和 DB 上使用 merge 函数。我看不出这是如何解决问题的,因为可能有另一个线程 C 与合并操作同时运行。声称纯函数式数据结构是无锁的,但使用合并函数听起来更像是最终一致性,这是另一回事。

【问题讨论】:

  • 这不是您问题的答案,但我认为如果您想共享对数据结构的修改,您应该考虑使用STM 作为discussed in this tutorial

标签: multithreading haskell data-structures functional-programming


【解决方案1】:

良好的观察力。但这只是意味着在存在“全局状态”的情况下进行并行处理是困难的或不可能的,无论编程语言如何。

在不纯的语言中,这不太明显。你可能认为你可以摆脱锁定、同步和所有高度复杂的代码。

而在纯语言中,您有 n 纯状态转换器,并且不能不意识到如果您将它们并行应用到某个初始状态 S0 您最终会得到这么多状态 S1S2、@ 987654325@...Sn

现在,纯度只是保证S0 的并行转换不会以任何方式相互干扰。它不能解决您的程序设计问题,例如该状态的含义,它是否可能过于粗略或过于细粒度,以及您是否可以从各种转换状态中计算最终结果。

【讨论】:

    【解决方案2】:

    函数式数据结构的重点是原子性。在您的场景中,DA 和 DB 保证是一致的,如何将它们合并为一致的值取决于您的应用程序(函数式编程不会为您解决所有问题)。然而,这仍然比您在命令式范式中得到的要多,其中 DA 和 DB 取决于线程的排序方式。

    【讨论】:

      【解决方案3】:

      总的来说,有很多方法可以做到这一点。在实践中,您可能希望确保 DA 或 DB 是规范的。如果这不能完成,那么应该有一个合并过程

      Thread A/B: 
      
      da  <- readSharedMemory at D
      da' <- modifyDict da
      mergeSharedMemory da'
      

      mergeSharedMemory 能够以一致的方式组合具有相似历史的两个字典。通常,这些类型的结构在数据库文献中作为 CRDT 得到了充分研究——“收敛复制数据类型”和“交换复制数据类型”。 INRIA Paper 有很多关于此的详细信息。

      【讨论】:

      • 我明白这在分布式系统中的意义所在。我仍然不相信这种机制等同于具有多线程的单系统环境中的无锁数据结构。
      • 我认为我对这个问题的反应较少,而对身体的反应较多。我不认为这是无锁的——你需要一个原子的读-合并-写操作。
      【解决方案4】:

      纯函数式数据结构是制作无锁可变数据结构的最简单方法。给定一个任意纯函数数据结构T,您可以定义一个无锁可变数据结构newtype U = U (IORef T)。给定一个任意函数f :: T -&gt; (T, a),你可以这样写

      mf :: U -> IO a
      mf (U ref) = atomicModifyIORef' ref f
      

      那么,为什么会有大量关于制作无锁数据结构的奇特技术的文献呢?因为并非所有数据结构都可以以纯粹的函数方式足够有效地实现。任何耗时过长的操作都会减慢所有线程并导致更新积压。

      【讨论】:

        【解决方案5】:

        您创建了第三个函数,采用 DA 和 DB 生成 DAB。

        【讨论】:

          猜你喜欢
          • 2017-10-11
          • 2020-05-12
          • 2016-01-02
          • 1970-01-01
          • 2011-06-19
          • 1970-01-01
          • 1970-01-01
          • 2017-03-10
          • 2019-10-05
          相关资源
          最近更新 更多