Risposte:
Consiglio vivamente "The Joy of Clojure" o "programmazione Clojure" per una risposta reale a questa domanda, posso riprodurre un breve frammento delle motivazioni per ciascuno:
inizia guardando questo video sulla nozione di identità e / o studiando qui .
L' accesso coordinato viene utilizzato quando due identità devono cambiare insieme, l'esempio classico è spostare denaro da un conto bancario a un altro, deve spostarsi completamente o per niente.
L' accesso non coordinato viene utilizzato quando è necessario aggiornare solo un'identità, questo è un caso molto comune.
L' accesso sincrono viene utilizzato quando si prevede che la chiamata attenda fino a quando tutte le identità non sono state risolte prima di continuare.
L' accesso asincrono è "spara e dimentica" e lascia che l'identità raggiunga il suo nuovo stato a suo tempo.
ensure
funzione: clojure.github.io/clojure/clojure.core-api.html#clojure.core/… per renderlo esplicito e più efficiente.
I riferimenti sono per lo stato che deve essere sincronizzato tra i thread. Se hai bisogno di tenere traccia di un sacco di cose diverse ea volte avrai bisogno di fare operazioni che scrivono su molte cose contemporaneamente, usa refs. Ogni volta che hai più pezzi di stato diversi, usare gli arbitri non è una cattiva idea.
Gli atomi sono per uno stato indipendente che deve essere sincronizzato tra i thread. Se non avrai mai bisogno di cambiare lo stato dell'atomo e qualsiasi altra cosa allo stesso tempo, usare at atom è sicuro (in particolare, se c'è un solo pezzo di stato nell'intero programma, puoi metterlo in un atomo) . Come esempio non banale, se stai cercando di memorizzare nella cache i valori di ritorno di una funzione (cioè memorizzarla), l'uso di un atomo è probabilmente sicuro: lo stato è invisibile a tutto ciò che è al di fuori della funzione, quindi non devi preoccuparti su un cambiamento di stato all'interno della funzione che incasina qualcosa.
Il punto principale degli agenti è che vengono eseguiti in un thread diverso. È possibile ottenere il valore dell'agente e dirgli di applicare una funzione al suo valore, ma non si sa quando verrà eseguita la funzione o a quale valore verrà applicata.
Le Vars servono quando è necessario memorizzare qualcosa in base ai thread. Se hai un programma multi-thread e ogni thread necessita del proprio stato privato, metti quello stato in un var.
Per quanto riguarda gli esempi del mondo reale, se fornisci un esempio di ciò che stai cercando di fare, possiamo dirti cosa usare.
Quando ho letto per la prima volta di questi tipi, ho anche faticato a capire dove potevo o dovevo usarli, quindi ecco la mia semplice risposta in inglese:
Usa una variabile quando i dati non cambieranno. Questo accade ogni volta che usi def
o la maggior parte delle funzioni che iniziano con def
like defn
.
Usa un atomo quando hai un singolo elemento che cambia. Un esempio potrebbe essere un contatore o un vettore a cui si desidera aggiungere elementi.
Usa un riferimento quando hai due o più cose che devono cambiare allo stesso tempo. Pensa alle "transazioni di database" se conosci. L'esempio canonico di questo è il trasferimento di denaro da un conto a un altro. Ogni account può essere memorizzato in un riferimento in modo che le modifiche possano essere apportate in modo che appaiano atomiche.
Usa un agente quando vuoi che qualcosa cambi ma non ti interessa quando. Potrebbe trattarsi di un lungo calcolo o di scrivere qualcosa su un file o un socket. Nota che con quest'ultimo dovresti usare send-off
.
Nota: apprezzo che ci sia molto di più in ognuno di questi, ma spero che questo dovrebbe darti un punto di partenza.
Ho scritto un articolo con un riepilogo della differenza tra loro e aiutare a scegliere quando utilizzare quale.
Condividi stato: quando si usano variabili, atomi, agenti e riferimenti?
Spero che aiuti le persone a cercare risposte in questo argomento.
Qualche scorciatoia dall'articolo dopo il suggerimento di @tunaci:
Vars
Le Vars sono globali per ogni thread.
Non modificare le variabili dopo la creazione. È tecnicamente possibile, ma è una cattiva idea per molte ragioni.
atomi
Condividi l'accesso allo stato mutevole per ogni thread. Il cambiamento avviene in modo sincrono. Riprova quando un altro thread cambia lo stato durante l'esecuzione.
Non utilizzare funzioni e funzioni non idempotenti con esecuzione a lungo termine
Agents
Condividi l'accesso allo stato mutevole per ogni thread. La modifica avviene in modo asincrono.
refs
Refs funziona in modo simile alle transazioni del database. La scrittura e la lettura sono protette in dosync. Puoi operare su molti ref in sicurezza nella transazione.
E diagramma di flusso quando usi quale:
Si prega di guardare l'immagine sul sito web, perché alcuni aggiornamenti sono sempre possibili.
È un argomento complesso e lungo per dare una risposta completa senza copia e articolo precedente, quindi per favore perdonami, ti reindirizzo al sito web :)
atomi, ref e agenti - un po 'di illuminazione qui http://blog.jayfields.com/2011/04/clojure-state-management.html
state-a
, mastate-b
nel farlo mi riferisco , ho comunque bisogno di unref
? Quindi non sta cambiando più cose ma si riferisce a più cose mentre ne cambia una?