【问题标题】:Concurrency with STM in ClojureClojure 中的 STM 并发
【发布时间】:2016-11-17 22:30:03
【问题描述】:

我目前正在学习 Clojure,但不确定如何使用 STM 进行并发。我要完成的任务非常简单,我有一个字符串向量,我想同时在每个字符串上运行一个函数,并用函数返回的内容替换字符串。

我目前可以使用 pmap 轻松做到这一点:

(pmap function string_vector)

如何在 Clojure 中使用 STM 做同样的事情?

【问题讨论】:

  • 我已经投票决定关闭它。这个问题没有很好地提出,因为它在线程协调空间中没有要求,这会导致 STM 作为解决方案中与问题相关的部分。这就像问我怎么用洗碗机吃苹果?

标签: concurrency clojure parallel-processing functional-programming stm


【解决方案1】:

STM 是一种跨线程共享数据的方式。如果您根本不需要协调(在此示例中不需要),则没有真正的理由使用 STM。

【讨论】:

  • 我明白了。我只是想知道用于学习目的。我很难理解 STM,任何帮助将不胜感激。
  • @Pythoner,仅仅因为它是为了“学习目的”并不意味着它不应该有意义。你的问题就像是说“我有一架飞机。我怎样才能用它来学习驾驶(汽车)?”当然,您可以沿着高速公路滑行您的飞机。但是,实际驾驶汽车并不明智——它们是完全不同的机器,具有非常不同的预期用途,并且控制方式也不同。
【解决方案2】:

clojure 中的 STM 是关于随着时间的推移保持可变事物的状态。这些具有随时变化状态的事物被称为具有“身份”。就像你一辈子都有一个“你”的身份一样,即使三个月大的“你”,到了120岁,也不一定能认出“你”。所以让我们在你的例子中加入一些可变的东西,这样我们就有了使用 STM 的借口:

让我们创建一个公开可用的可变位置来存储字符串,然后并行更改它们:

user> (def current-strings (ref ["a" "b" "c"]))
#'user/current-strings
user> (dosync (alter current-strings (fn [the-string-at-this-instant]
                                       (pmap #(.toUpperCase %) the-string-at-this-instant))))
("A" "B" "C")
user> @current-strings
("A" "B" "C")
user> 

在这个例子中,我们创建了一个事务,通过对其应用一个函数来改变我们的字符串集合的状态。在内部,该函数碰巧并行计算新值。

为了让这更有趣,让我们创建一个可变事物的向量,然后在其自己的事务中并行更新一堆独立可变的事物:

user> (def current-strings [(ref "a") (ref "b") (ref "c")])
#'user/current-strings

user> (doall
       (pmap (fn [ref-to-update]
               (dosync (alter ref-to-update #(.toUpperCase %))))
             current-strings))
("A" "B" "C")

user> (map deref current-strings)
("A" "B" "C")
user> 

如您所见,这些都不需要 STM,因为所有这些操作都可以使用 clojure 中的其他可变类型来处理,原子将是一个不错的选择。和裁判一起玩也很有趣!玩得开心!

【讨论】:

  • 这里要小心。因为 pmap 和 map 一样是惰性的,所以你不应该仅仅评估它的副作用,如果你想确保所有的结果都得到实现,你应该强制整个事情。如果您没有碰巧在 repl 中打印此内容,则这些更改都不会保证发生(实际上只有前 32 个会发生,因为分块)。注意gist.github.com/amalloy/906a65d5851ab61554b12482a8dbcb4a 中重复的 32。
  • 好点! “懒虫”潜伏在这里。我在里面放了一个doall。还值得注意的是,如果将 dosync 放在 pmap 之外,它就不起作用。
  • 这一切没有意义。你在一个字符串上调用 doall ,这是一个空操作。再次,在超过 32 个元素的情况下尝试它,而不将结果打印到 repl 以查看它是否正确。您需要执行 pmap 的结果,而不是其中的任何内容。
  • 我在没有实际测试示例的情况下完全打了它,我现在会正确修复它。谢谢你让我诚实。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多