Réponses:
Je recommande vivement "The Joy of Clojure" ou "programmation Clojure" pour une vraie réponse à cette question, je peux reproduire un petit aperçu des motivations pour chacun:
commencez par regarder cette vidéo sur la notion d'identité et / ou étudiez ici .
L' accès coordonné est utilisé lorsque deux identités doivent changer ensemble, l'exemple classique consiste à transférer de l'argent d'un compte bancaire à un autre, il doit soit bouger complètement, soit pas du tout.
L' accès non coordonné est utilisé lorsqu'une seule identité doit être mise à jour, c'est un cas très courant.
L' accès synchrone est utilisé lorsque l'appel est censé attendre que toutes les identités soient réglées avant de continuer.
L' accès asynchrone est "feu et oublie" et laisse l'identité atteindre son nouvel état à son propre rythme.
ensure
fonction: clojure.github.io/clojure/clojure.core-api.html#clojure.core / ... pour rendre cela explicite et plus efficace.
Les références sont pour l'état qui doit être synchronisé entre les threads. Si vous avez besoin de suivre un tas de choses différentes et que vous aurez parfois besoin de faire des opérations qui écrivent plusieurs choses à la fois, utilisez refs. Chaque fois que vous avez plusieurs états différents, utiliser des références n'est pas une mauvaise idée.
Les atomes sont pour un état indépendant qui doit être synchronisé entre les threads. Si vous n'aurez jamais besoin de changer l'état de l'atome et quoi que ce soit d'autre en même temps, utiliser at atom est sûr (en particulier, s'il n'y a qu'un seul élément d'état dans tout le programme, vous pouvez le mettre dans un atome) . À titre d'exemple non trivial, si vous essayez de mettre en cache les valeurs de retour d'une fonction (c'est-à-dire de la mémoriser), l'utilisation d'un atome est probablement sûre - l'état est invisible pour tout ce qui se trouve en dehors de la fonction, vous n'avez donc pas à vous inquiéter à propos d'un changement d'état dans la fonction qui gâche quoi que ce soit.
Le point principal des agents est qu'ils s'exécutent dans un thread différent. Vous pouvez obtenir la valeur de l'agent et lui dire d'appliquer une fonction à sa valeur, mais vous ne savez pas quand la fonction sera exécutée ou à quelle valeur la fonction sera appliquée.
Les Vars sont pour quand vous avez besoin de stocker quelque chose sur une base par thread. Si vous avez un programme multi-thread et que chaque thread a besoin de son propre état privé, placez cet état dans une variable var.
En ce qui concerne les exemples du monde réel, si vous donnez un exemple de ce que vous essayez de faire, nous pouvons vous dire quoi utiliser.
Lorsque j'ai lu pour la première fois sur ces types, j'ai également eu du mal à comprendre où je pouvais ou devrais utiliser chacun d'eux, alors voici ma réponse en anglais simple:
Utilisez une variable lorsque les données ne changeront pas. Cela se produit chaque fois que vous utilisez def
ou la plupart des fonctions commençant par def
like defn
.
Utilisez un atome lorsque vous avez un seul élément qui change. Un exemple peut être un compteur ou un vecteur auquel vous souhaitez ajouter des éléments.
Utilisez une référence lorsque vous avez deux choses ou plus qui doivent changer en même temps. Pensez aux «transactions de base de données» si vous êtes familier. L'exemple canonique de ceci est le transfert d'argent d'un compte à un autre. Chaque compte pourrait être stocké dans une référence afin que des modifications puissent être apportées pour apparaître atomique.
Utilisez un agent lorsque vous voulez que quelque chose change mais que vous ne vous souciez pas du moment. Cela peut être un long calcul ou écrire quelque chose dans un fichier ou une socket. Notez qu'avec ce dernier, vous devez utiliser send-off
.
Remarque: j'apprécie qu'il y ait beaucoup plus à chacun d'entre eux, mais j'espère que cela devrait vous donner un point de départ.
J'ai écrit un article avec un résumé de la différence entre eux et j'ai aidé à choisir quand utiliser lequel.
Partager l'état - quand utiliser des vars, des atomes, des agents et des refs?
J'espère que cela aidera les gens à chercher des réponses à ce sujet.
Un raccourci de l'article après la suggestion @tunaci:
Vars
Les Vars sont globales pour chaque thread.
Ne changez pas de vars après la création. C'est techniquement possible, mais c'est une mauvaise idée pour de nombreuses raisons.
Atomes
Partagez l'accès à l'état mutable pour chaque thread. Le changement se produit de manière synchrone. Réessayez lorsqu'un autre thread change l'état pendant l'exécution.
N'utilisez pas de fonctions non idempotentes et de fonctions avec une exécution de longue durée
Agents
Partagez l'accès à l'état mutable pour chaque thread. Le changement se produit de manière asynchrone.
Réfs
Refs fonctionne de manière similaire aux transactions de base de données. L'écriture et la lecture sont protégées dans dosync. Vous pouvez opérer sur de nombreuses références en toute sécurité en transaction.
Et organigramme lorsque vous utilisez lequel:
Veuillez regarder l'image sur le site Web, car certaines mises à jour sont toujours possibles.
Il est complexe et long de donner une réponse complète sans copie ni article passé, alors pardonnez-moi, je vous redirige vers le site Web :)
atomes, références et agents - quelques éclairages ici http://blog.jayfields.com/2011/04/clojure-state-management.html
state-a
, mais que je me réfère àstate-b
cela, j'ai toujours besoin d'unref
correct? Il ne s'agit donc pas de changer plusieurs choses mais de faire référence à plusieurs choses tout en changeant l'une d'entre elles?