2012-02-03 7 views

Respuesta

37

Las referencias son para el estado que debe sincronizarse entre subprocesos. Si necesita hacer un seguimiento de un montón de cosas diferentes y algunas veces necesitará hacer operaciones que escriban en varias de las cosas a la vez, use refs. Cada vez que tenga múltiples piezas diferentes de estado, usar refs no es una mala idea.

Los átomos son para un estado independiente que debe sincronizarse entre subprocesos. Si nunca necesitará cambiar el estado del átomo y cualquier otra cosa al mismo tiempo, usar atom es seguro (en particular, si solo hay un estado en todo el programa, puede ponerlo en un átomo) . Como ejemplo no trivial, si intenta almacenar en caché los valores de retorno de una función (es decir, memorizarla), usar un átomo probablemente sea seguro: el estado es invisible para todo lo que está fuera de la función, por lo que no tiene que preocuparse acerca de un cambio de estado dentro de la función arruinando todo.

El punto principal de los agentes es que se ejecutan en un hilo diferente. Puede obtener el valor del agente y decirle que aplique una función a su valor, pero no sabe cuándo se ejecutará la función ni a qué valor se aplicará la función.

Vars son para cuando necesita almacenar algo por subproceso. Si tiene un programa de subprocesos múltiples y cada subproceso necesita su propio estado privado, ponga ese estado en una var.

En cuanto a ejemplos del mundo real, si proporciona un ejemplo de lo que está tratando de hacer, podemos decirle qué usar.

147

le recomiendo "La alegría de Clojure" o "programación Clojure" para una verdadera respuesta a esta pregunta, puedo reproducir un corto tijeretazo-it de las motivaciones de cada uno:

empezar por ver this video on the notion of Identity y/o studying here.

  • las referencias son para Coordinado síncrono acceso a "múltiples identidades".
  • Los átomos son para sincrónico sin coordinación acceso a una sola identidad.
  • Los agentes son para Acceso asíncrono no coordinado a una única identidad.
  • Vars son para el hilo local identidades aisladas con un valor predeterminado compartido.

Coordinado de acceso se utiliza cuando dos identidades tiene que cambiar juntos, el ejemplo clásico está moviendo dinero de una cuenta bancaria a otra, es necesario que sea moverse por completo o no en absoluto.

El acceso descoordinado se usa cuando solo una identidad necesita actualizarse, este es un caso muy común.

El acceso sincrónico se usa cuando se espera que la llamada espere hasta que todas las identidades se hayan resuelto antes de continuar.

asincrónico acceso es "disparar y olvidar" y dejar que la identidad alcance su nuevo estado en su propio tiempo.

+0

En el acceso coordinada, si quiero único cambio 'estado a' , pero consulte 'state-b' al hacerlo, ¿todavía necesito una' ref' correcta? Entonces, ¿no está cambiando varias cosas sino que se refiere a múltiples cosas al cambiarlas? –

+0

Sí, parece entender correctamente que state-a y state-b deben ser ambos refs. Si desea que el nuevo valor en state-a se base en una combinación consistente de los valores en ay b. Necesita que ese nuevo valor se haya calculado en un contexto en el que state-a y y state-b coinciden entre sí. Cuando ambos son refs, si b cambia a la mitad, la transacción se reiniciará y usará los nuevos valores de a y b. considere usar la función 'ensure': http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/ensure para hacer esto más explícito y más eficiente. –

+3

¿Se podría agregar una explicación de lo que significa Aislar con el valor predeterminado compartido para completar la respuesta? –

27

Cuando leí por primera vez acerca de este tipo, que también tuvo problemas para entender donde podría o debería utilizar cada uno de ellos así que aquí está mi llanura respuesta Inglés:

Use una var cuando los datos no cambien. Esto sucede cada vez que usa def o la mayoría de las funciones que comienzan con def como defn.

Utilice un átomo cuando tenga un único elemento que cambie. Un ejemplo podría ser un contador o un vector al que desee agregar elementos.

Utilice una referencia cuando tenga dos o más cosas que deben cambiar al mismo tiempo. Piense en "transacciones de base de datos" si está familiarizado. El ejemplo canónico de esto es transferir dinero de una cuenta a otra. Cada cuenta puede almacenarse en una referencia para que los cambios puedan hacerse atómicos.

Utilice un agente cuando desee que algo cambie pero no le importa cuándo. Esto puede ser un cálculo largo o escribir algo en un archivo o socket. Tenga en cuenta que con este último debe usar send-off.

Nota: Aprecio que haya mucho más para cada uno de estos, pero espero que esto te dé un punto de partida.

+0

Muchas gracias por su respuesta clara :-) Ayuda mucho a un novato de Clojure como yo. – gosukiwi

+0

¡Bueno! Gracias... –

16

Escribí el artículo con un resumen de la diferencia entre ellos y ayuda a elegir cuándo usar cuál.

Share state - when use vars, atoms, agents and refs?

espero que ayudará a las personas que buscan respuestas en ese tema.

Algunos acceso directo del artículo después sugerencia @tunaci:

Vars

Vars son globales por cada hilos.

No cambies vars después de crear. Es técnicamente posible, pero es una mala idea por muchas razones.

Átomos

compartir el acceso a estado mutable por cada hilos. El cambio ocurre sincrónicamente. Vuelva a intentar cuando otro hilo cambie el estado durante la ejecución.

No utilice funciones y funciones no idempotente con mucho tiempo de ejecución

Agentes

compartir el acceso a estado mutable por cada hilos. El cambio ocurre de forma asíncrona.

Refs

Refs funciona de forma similar a las transacciones de bases de datos. Escribir y leer son proteger en dosync. Puede operar en muchos refs seguros en la transacción.

Y diagrama de flujo cuando el uso de los cuales uno: flowchart

Por favor mirar la imagen en la página web, ya que algunas actualizaciones son siempre posibles.

Es complejo y un tema de largo para dar respuesta plena y sin copia & artículo pasado, así que por favor perdóneme que le redirigirá a la página web :)

Cuestiones relacionadas