2012-03-12 13 views
7

Hola chicos: La documentación para el clojure "átomo" establece que -Las condiciones de carrera y átomos clojure

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

Sin embargo- una condición de carrera se define no sólo en términos de un cambio, sino más bien, en el contexto de operaciones lógicas paralelas en diferentes hilos.

Me pregunto: ¿cuál es el significado de la garantía de que "Los cambios en los átomos están siempre libres de condiciones de carrera"? En java, tenemos primitivas atómicas que admiten ciertas operaciones seguras de subprocesos que son específicas (por ejemplo, AtomicInteger admite una operación "getAndIncrement"). Pero los átomos Clojure son de tipo-agnóstico, por ejemplo, podemos invocar:

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

La flexibilidad del método átomo significa que Clojure, bajo el capó, no es "inteligente" proveer-tipo específico atómica/thread-safe operaciones para átomos.

Por lo tanto, me pregunto - ¿qué es exactamente el método átomo de "hacer" a nuestros objetos

Respuesta

11

Un atom es efectivamente un lugar de almacenamiento atómica que se garantiza que (es decir, se trata simplemente de la sincronización de todo el objeto?) estar seguro de subprocesos

Los átomos son similares a los tipos de datos atómicos de Java (como AtomicReference), pero en realidad son algo más potentes ya que un átomo le permite utilizar una función arbitraria para actualizar el átomo. Ejemplo:

(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" 

En el ejemplo anterior, la operación swap! comporta atómicamente, a pesar de que la operación appender estamos pasando a que podría potencialmente ser una función bastante complejo. En efecto, los átomos le permiten usar una operación de actualización arbitraria de forma atómica (normalmente debería apegarse a funciones puras, ya que es posible llamar a la función varias veces en caso de conflicto).

Los átomos obviamente no garantizan la seguridad de subprocesos de los objetos que coloques dentro de ellos (por ejemplo, si pones una Java ArrayList no sincronizada dentro, entonces sigue siendo inseguro para el uso concurrente). Sin embargo, si te apegas a los tipos de datos inmutables de Clojure, que son completamente seguros para hilos, estarás bien.

+5

* "Se garantiza que estas funciones se ejecutarán secuencialmente" * - esto no es exactamente lo que garantiza el 'átomo '. La garantía real es que 'swap af' recuerda el valor de' a', lo pasa a 'f' y si el valor de' a' después de 'f' está terminado sigue siendo igual al valor anterior, luego se reemplaza por el resultado de 'f'. Muchas otras funciones se podrían haber aplicado a 'a' mientras tanto, siempre que sus efectos se anulen mutuamente. –

+1

@Rafal - gracias buen lugar, he actualizado la respuesta para ser un poco más preciso. – mikera

+0

@myself: la comparación subyacente es en realidad Java == (identidad del objeto), así que en lugar de "igual" debería haber escrito "idéntico" y en lugar de "cancelar el uno al otro" -> "dejar el átomo haciendo referencia al mismo objeto" . –

Cuestiones relacionadas