比赛条件和clojure原子

jay*_*100 7 java multithreading atomic clojure

大家好:clojure"atom"的文档说明 -

"Changes to atoms are always free of race conditions."
Run Code Online (Sandbox Code Playgroud)

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

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

  (atom "Hi im a string")  Or
  (atom (.getClass Object))
Run Code Online (Sandbox Code Playgroud)

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

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

mik*_*era 12

原子有效地是保证线程安全的原子的存储位置.

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

(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"
Run Code Online (Sandbox Code Playgroud)

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

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

  • *"这些函数保证按顺序执行"* - 这不是`atom`保证的.实际的保证是`swap af`记住`a`的值,将它传递给`f`,如果`f`之后的`a`的值仍然等于旧值,则它被替换为`f`的结果.在此期间,只要它们的效果相互抵消,许多其他功能就可以应用于"a". (5认同)