Respuestas:
Recomiendo encarecidamente "The Joy of Clojure" o "programar Clojure" para obtener una respuesta real a esta pregunta, puedo reproducir un breve fragmento de las motivaciones de cada uno:
Comience viendo este video sobre la noción de Identidad y / o estudie aquí .
El acceso coordinado se usa cuando dos Identidades deben cambiar juntas, el ejemplo clásico es mover dinero de una cuenta bancaria a otra, debe moverse completamente o no moverse en absoluto.
El acceso descoordinado se usa cuando solo se necesita actualizar una identidad, este es un caso muy común.
El acceso sincrónico se utiliza cuando se espera que la llamada espere hasta que todas las identidades se hayan establecido antes de continuar.
El acceso asincrónico es "disparar y olvidar" y dejar que la identidad alcance su nuevo estado en su propio tiempo.
ensure
función: clojure.github.io/clojure/clojure.core-api.html#clojure.core/… para hacer esto explícito y más eficiente.
Las referencias son para el estado que debe sincronizarse entre subprocesos. Si necesita realizar un seguimiento de un montón de cosas diferentes y, a veces, necesitará realizar operaciones que escriban en varias de las cosas a la vez, use refs. Siempre que tenga varios estados diferentes, usar referencias 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 at atom es seguro (en particular, si solo hay una parte del estado en todo el programa, puede ponerlo en un átomo) . Como ejemplo no trivial, si está tratando de 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 debe preocuparse sobre un cambio de estado dentro de la función que estropea algo.
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.
Los Vars son para cuando necesita almacenar algo por hilo. Si tiene un programa de subprocesos múltiples y cada subproceso necesita su propio estado privado, ponga ese estado en una var.
En lo que respecta a los ejemplos del mundo real, si proporciona un ejemplo de lo que está intentando hacer, podemos decirle qué utilizar.
Cuando leí por primera vez sobre estos tipos, también me costó entender dónde podría o debería usar cada uno, así que aquí está mi respuesta en inglés simple:
Utilice una var cuando los datos no cambien. Esto sucede siempre que usa def
o la mayoría de las funciones que comienzan con def
like defn
.
Use un átomo cuando tenga un solo elemento que cambie. Un ejemplo podría ser un contador o un vector al que desea 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 podría almacenarse en una referencia para que se puedan hacer cambios para que parezcan atómicos.
Utilice un agente cuando desee que algo cambie pero no le importe cuándo. Esto podría 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 hay mucho más en cada uno de estos, pero espero que esto le dé un punto de partida.
Escribí un artículo con un resumen de la diferencia entre ellos y ayudé a elegir cuándo usar cuál.
Estado compartido: ¿cuándo se usan vars, átomos, agentes y referencias?
Espero que ayude a las personas a buscar respuestas en ese tema.
Algunos atajos del artículo después de la sugerencia de @tunaci:
Vars
Los Vars son globales para todos los hilos.
No cambie vars después de crear. Es técnicamente posible, pero es una mala idea por muchas razones.
Átomos
Comparta el acceso al estado mutable para cada hilo. El cambio ocurre sincrónicamente. Vuelva a intentarlo cuando otro subproceso cambie el estado durante la ejecución.
No utilice funciones no idempotentes y funciones con ejecución prolongada
Agentes
Comparta el acceso al estado mutable para cada hilo. El cambio se produce de forma asincrónica.
Refs
Refs funciona de manera similar a las transacciones de bases de datos. La escritura y la lectura están protegidas en dosync. Puede operar en muchas referencias seguras en la transacción.
Y diagrama de flujo cuando use cuál:
Mire la imagen en el sitio web, porque siempre es posible realizar algunas actualizaciones.
Es complejo y un tema largo para dar una respuesta completa sin copia y artículo anterior, así que perdóneme, lo redirecciono al sitio web :)
átomos, referencias y agentes: algo de iluminación aquí http://blog.jayfields.com/2011/04/clojure-state-management.html
state-a
, pero me refiero alstate-b
hacerlo, todavía necesito unref
correcto? Entonces, ¿no se trata de cambiar varias cosas, sino de hacer referencia a varias cosas mientras se cambia alguna de ellas?