Расовые условия и замыкания Атомов - PullRequest
7 голосов
/ 12 марта 2012

Привет, ребята: Документация для 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 Ответ

12 голосов
/ 12 марта 2012

atom - это фактически атомарное хранилище, которое гарантированно является поточно-ориентированным.

Атомы похожи на атомарные типы данных 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"

В приведенном выше примере операция swap! ведет себя атомарно, даже если передаваемая ей операция appender потенциально может быть довольно сложной функцией.Фактически, атомы позволяют вам использовать произвольную операцию обновления атомарным способом (обычно вы должны придерживаться чистых функций, поскольку в случае конфликта функция может быть вызвана несколько раз).

Атомыочевидно, не гарантирует потокобезопасность объектов, которые вы помещаете в них (например, если вы помещаете несинхронизированный Java ArrayList внутри, тогда это все еще небезопасно для одновременного использования).Однако, если вы будете придерживаться неизменных типов данных Clojure, которые полностью поточнобезопасны, тогда у вас все будет хорошо.

...