【问题标题】:Real alternatives to Clojure's concurrency primitives in ScalaScala 中 Clojure 并发原语的真正替代品
【发布时间】:2013-11-29 19:47:03
【问题描述】:

在 Clojure 中,我有四个原语来管理并发场景

  1. Refs - 管理协调、同步对共享状态的更改
  2. Atoms - 管理不协调的、同步的对共享状态的更改
  3. 代理 - 管理对共享状态的异步更改
  4. Vars - 管理线程本地状态

我的问题是 - 在 Scala 中是否有成熟的等价物?

假设 - 我将假设:

  • Actor 是解决代理所面临问题的不同方式 - 但它们绝不是替代品
  • 我知道 Scala 中有代理库 - 我很想知道它们是否被认为是成熟的

【问题讨论】:

  • Scala 变量不提供线程安全。但是,大多数优秀的函数式 Scala 编码人员倾向于只在安全封装可变状态的上下文中使用 var,他们根本就在其中使用它们。
  • @flavian 不是那些演员库吗?如果是这样,请参阅 OP 的第一个假设。

标签: scala concurrency clojure


【解决方案1】:

您为 Clojure are based in software transactional memory. 列出的大多数并发构造正因为如此,我认为您基本上只是在询问 Scala 中的 STM 支持。根据Akka documentation 的说法,Scala 中 STM 的最佳选择是ScalaSTM,他们说它实际上会在未来某个时候包含在 Scala 标准库中。

ScalaSTM 支持 Agents 和 Refs(我相信它们实际上是基于 Clojure 版本的)。我认为 Atom 的必然结果是 Ref.single 类型,它只是一个您可以在 atomic 块之外使用的引用。

根据您的用例,var 的良好替代品是 Java 的 ThreadLocal 或 Scala 的 DynamicVariable。如果您想要的只是线程本地数据,请使用ThreadLocal,但如果您确实需要动态绑定,那么我认为您需要DynamicVariable

【讨论】:

  • 其实只有 Clojure Refs 使用 STM。原子不是事务性的,因为您不能以原子方式更新多个原子。他们不参与 STM 交易。代理稍微参与,但只是在任何代理调度都延迟到事务成功完成的意义上。但是,如果代理操作失败,它不会导致事务失败。变量提供线程局部值(动态变量是这种情况的特例)。因此,每种类型都提供了不同的方式来管理(可能是并发的)状态,每种方式都有不同的用例。
  • @NathanDavis - 你说得对,原子并不真的需要 STM。但是,您可以将原子上的操作视为 STM 的简并情况,实现它所需要的只是 CAS。这就是 ScalaSTM 提供 Ref.single 实现的原因,它允许您在 Ref 上执行交换和 CAS 等操作,而无需将其显式包装在原子块中。我想我明白你的意思,我会编辑我的答案,这样措辞会更清楚。
猜你喜欢
  • 2011-12-10
  • 2015-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 2012-08-08
  • 2011-11-05
  • 1970-01-01
相关资源
最近更新 更多