比赛条件和clojure原子

时间:2012-03-12 01:20:01

标签: java multithreading clojure atomic

大家好:clojure“atom”的文档说明了 -

"Changes to atoms are always free of race conditions."

然而,竞争条件不仅定义在变化方面,而且定义在不同线程中并行逻辑运算的上下文中。

我想知道 - “对原子的变化总是没有竞争条件”的保证意义何在?在java中,我们有原子基元,它支持某些特定的线程安全操作(例如,AtomicInteger支持“getAndIncrement”操作)。但是Clojure原子是类型无关的,例如,我们可以调用:

  (atom "Hi im a string")  Or
  (atom (.getClass Object))

原子方法的灵活性意味着,引擎盖下的Clojure并非“巧妙地”为原子提供特定类型的原子/线程安全操作。

因此,我会问 - 原子方法对我们的对象“做什么”究竟是什么(即它只是简单地同步整个对象?)

1 个答案:

答案 0 :(得分:12)

atom实际上是一个保证线程安全的原子存储位置。

Atoms类似于Java的原子数据类型(如AtomicReference),但实际上更强大,因为atom允许您使用任意函数来更新原子。例如:

(def a (atom "foo"))

(defn appender [x]
  "Higher order function that returns a function which appends a specific string"
  (fn [s] 
    (str s x)))

(swap! a (appender "bar"))
=> "foobar"

在上面的例子中,swap!操作以原子方式运行,即使我们传递给它的appender操作可能是一个非常复杂的函数。实际上,atoms允许您以原子方式使用任意更新操作(您通常应该坚持使用纯函数,因为在争用情况下可以多次调用该函数。)

Atoms显然不保证您放入其中的对象的线程安全(例如,如果您将不同步的Java ArrayList放入其中,那么对于并发使用它仍然是不安全的)。但是,如果你坚持Clojure的不可变数据类型,这些数据类型都是完全线程安全的,那么你就会很好。