【问题标题】:Is Clojure lockfree by using lockfree algorithms?Clojure 是否使用无锁算法实现无锁?
【发布时间】:2012-06-17 09:57:06
【问题描述】:

我的 Clojure 任务正在取得进展(在 4clojure.com 上解决了大约 80 个问题),我继续阅读和编码并尝试“得到它”。

现在我对 Clojure 被设计为“无锁并发”感到有些困惑。我对死锁非常了解(例如:“我编写的 Java 代码很糟糕,最终陷入死锁”,而不是 “我是并发专家” em>)。我也读过这个:

Why is lockless concurrency such a big deal (in Clojure)?

我意识到 Clojure 程序不能死锁是多么的棒。

但我有点困惑:这样的壮举是通过在后台实现无锁算法实现的,还是使用了潜在的“可死锁”算法,但使用正确的实现保证永远不会死锁(这会以某种方式“隐藏” Clojure 程序员)?

最近有关于无锁算法的黑客新闻讨论:

http://news.ycombinator.com/item?id=4103921

参考 1024cores.net 上的以下“无锁算法”页面:

http://www.1024cores.net/home/lock-free-algorithms

我不明白这篇文章和 Clojure 下并发如何工作之间的关系。

这让我完全困惑:当我在 Clojure 中开发并发程序时,这是否意味着“锁和无锁算法”对我来说不是问题?

【问题讨论】:

  • 另外,lock-freelockless 标签都没有 wiki。它们是同义词吗?这两个标签不应该合并还是它们是不同的东西?
  • Clojure 拥有非常不同寻常的深刻概念,因此[几乎] 不可能通过简单地学习语法和解决难题来“获得”它们。如果您的目标是“真正获得 Clojure”,那么我建议您阅读一本好的 Clojure 书籍。亚马逊上有大约 5 个。那么我保证你能回答你自己的问题。
  • @Dmitry Kakurin:我可以看出你是新来的。您的评论表明您不了解 SO 的工作原理。 SO 是一个提问的地方,就像这个得到了 8 个赞和 3 个收藏的地方。 SO 不是一个让你上马并通过告诉他们不会“得到它”并且他们不会通过解决难题来向正在学习新语言的人撒尿的地方应该阅读书籍来回答他们自己的问题,而不是在 SO 上问他们。现在如果 “真的想获得 StackOverflow” 我建议你阅读 SO FAQ ; )
  • @Dmitry Kakurin:作为 SO 工作原理的提示:它通过让人们参与其中来工作。看看我的问题和两个很好的答案:谁确实为 SO 带来了更多价值?我通过问这个问题和两个回答得很好的人或者你,你的尖刻评论淡化了我和我的解谜活动?
  • 你的暴力反应是无缘无故的。但最重要的是,您错过了我的观点:如果您的目标是让自己熟悉该语言,那么您所做的就很好(而且我绝不是在试图淡化您的努力)。但是,如果您想“了解”Clojure 在概念上与许多其他语言的不同之处,那么阅读一本好书是必经之路,解决难题不太可能让您到达那里。再次尝试阅读我的评论,而不是作为攻击,而是作为基于经验的建议。然后随意忽略它。

标签: concurrency clojure locking lock-free lockless


【解决方案1】:

一般而言,Clojure 通过正确处理时间来避免锁问题在时间 2(更新后)成为该对象,在该过程中它既不是第一个也不是第二个,因此我们使用锁来确保它仅在此转换之前或之后可见。协调锁由此而来,而死锁则由此而来......

它是算法、数据结构和时间的组合。

Clojure 通过结合不可变数据结构、函数式编程和协调时间模型(参考、原子、代理等)来做到这一点。在这个模型中,一个函数获取一些东西并生成它的下一个版本,同时保留过去,只要有人在看它(直到 GC 找到它)

  • 不可变数据结构:Clojure 的集合在 FP 意义上是持久的。制作新版本后,旧副本“仍然存在”。这样观察者就不需要锁定对象,因为它们永远不会从它们下面变出来。可能存在基于他们正在查看的版本的较新版本,但不会改变他们的副本。

  • 函数式编程:纯粹(或尽可能接近没有区别)函数在某个时间点获取一个集合并生成下一个版本,而不共享其内部状态,因此不需要锁定。这还有许多其他好处。

  • Coordinated time:当确实需要协调多个对象时,就像任何有趣的系统一样,Clojure 的时间模型就会发挥作用。不同的目的有不同的机制。这有一个内部用于计算时间增量的锁,因此恰好有一个时间零,一个时间一和一个时间 N。所以它不是严格无锁的。 STM 包含您永远*不需要与之交互的锁


*好吧...几乎从来没有;-)

【讨论】:

    【解决方案2】:

    如果您搜索 Clojure 源代码,特别是 .java 文件,您会发现很多对 java.util.concurrent 包的引用。 java.util.concurrent 软件包是纽约州立大学奥斯威戈分校的 Doug Lea 数十年来对并发性研究的结晶。具体来说,引用原子变量类(例如AtomicReference)允许访问“比较和交换”(也称为“比较和设置”,或CAS)instruction。 CAS 指令有点难以解释(我在下面提供了参考),但正确使用 CAS 是算法“无锁”的核心(至少在 Java 世界中)。无锁算法最终会为高并发应用程序带来更高的吞吐量和更少的争用;正是 Clojure 所针对的域。

    要深入了解这个主题,请阅读 Brian Goetz 的 Java 并发实践。另请参阅同一作者的article

    附带说明一下,我总是发现很难直接使用 java.util.concurrent 包,即使它已经发展了。对我来说只是感觉太低级了。 Clojure 的美妙之处在于它提供了对专家并发库的访问,但通过非常易于使用的软件事务内存 (STM) 抽象来实现。这真是一项了不起的成就。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 2012-08-31
      相关资源
      最近更新 更多