Odpowiedzi:
Gorąco polecam "The Joy of Clojure" lub "Programowanie Clojure", aby uzyskać prawdziwą odpowiedź na to pytanie, mogę odtworzyć krótki fragment motywacji dla każdego z nich:
zacznij od obejrzenia tego filmu na temat tożsamości i / lub studiowania tutaj .
Skoordynowany dostęp jest używany, gdy dwie Tożsamości muszą się zmienić razem, klasycznym przykładem jest przenoszenie pieniędzy z jednego konta bankowego na drugie, muszą one zostać przeniesione całkowicie lub wcale.
Nieskoordynowany dostęp jest używany, gdy tylko jedna tożsamość wymaga aktualizacji, jest to bardzo częsty przypadek.
Dostęp synchroniczny jest używany, gdy połączenie ma czekać, aż wszystkie tożsamości zostaną rozliczone, zanim będzie kontynuowane.
Dostęp asynchroniczny to „odpal i zapomnij” i pozwala Tożsamości osiągnąć nowy stan we własnym czasie.
ensure
funkcji: clojure.github.io/clojure/clojure.core-api.html#clojure.core/, aby uczynić to wyraźnym i bardziej wydajnym.
Odniesienia dotyczą stanu, który musi być zsynchronizowany między wątkami. Jeśli chcesz śledzić kilka różnych rzeczy, a czasami będziesz musiał wykonać operacje, które zapisują kilka rzeczy naraz, użyj refs. Za każdym razem, gdy masz wiele różnych stanów, używanie referencji nie jest złym pomysłem.
Atomy są dla niezależnego stanu, który należy zsynchronizować między wątkami. Jeśli nigdy nie będziesz musiał zmieniać stanu atomu i czegokolwiek innego w tym samym czasie, użycie at atom jest bezpieczne (w szczególności, jeśli w całym programie jest tylko jeden element stanu, możesz umieścić go w atomie) . Jako nietrywialny przykład, jeśli próbujesz buforować wartości zwracane funkcji (tj. Zapamiętać ją), użycie atomu jest prawdopodobnie bezpieczne - stan jest niewidoczny dla wszystkiego poza funkcją, więc nie musisz się martwić o zmianie stanu wewnątrz funkcji, która coś psuje.
Głównym punktem agentów jest to, że działają w innym wątku. Możesz uzyskać wartość agenta i powiedzieć mu, aby zastosował funkcję do jego wartości, ale nie wiesz, kiedy funkcja zostanie uruchomiona ani do jakiej wartości zostanie zastosowana.
Zmienne są używane, gdy musisz przechowywać coś na podstawie wątku. Jeśli masz program wielowątkowy i każdy wątek potrzebuje własnego stanu prywatnego, umieść ten stan w zmiennej.
Jeśli chodzi o przykłady ze świata rzeczywistego, jeśli podasz przykład tego, co próbujesz zrobić, możemy Ci powiedzieć, czego użyć.
Kiedy po raz pierwszy przeczytałem o tych typach, starałem się również zrozumieć, gdzie mogę lub powinienem używać każdego z nich, więc oto moja prosta angielska odpowiedź:
Użyj zmiennej, jeśli dane nie ulegną zmianie. Dzieje się tak, gdy używasz def
lub większość funkcji, które zaczynają się def
niczym defn
.
Użyj atomu, jeśli masz jeden element, który się zmienia. Przykładem może być licznik lub wektor, do którego chcesz dodać elementy.
Użyj ref, jeśli masz dwie lub więcej rzeczy, które muszą się zmienić w tym samym czasie. Pomyśl o „transakcjach baz danych”, jeśli znasz. Kanonicznym przykładem tego jest przelewanie pieniędzy z jednego konta na drugie. Każde konto może być przechowywane w referencji, aby zmiany wyglądały niepodzielnie.
Skorzystaj z usług agenta, jeśli chcesz coś zmienić, ale nie obchodzi Cię kiedy. Może to być długie obliczenia lub zapisywanie czegoś do pliku lub gniazda. Zauważ, że z tym drugim powinieneś użyć send-off
.
Uwaga: doceniam, że w każdym z nich jest o wiele więcej, ale mam nadzieję, że powinno to dać ci punkt wyjścia.
Napisałem artykuł podsumowujący różnice między nimi i pomagający wybrać, kiedy z nich skorzystać.
Udostępnij stan - kiedy używasz zmiennych, atomów, agentów i referencji?
Mam nadzieję, że pomoże to ludziom szukającym odpowiedzi w tym temacie.
Kilka skrótów z artykułu po sugestii @tunaci:
Vars
Vars są globalne dla każdego wątku.
Nie zmieniaj zmiennych po utworzeniu. Jest to technicznie możliwe, ale z wielu powodów jest to zły pomysł.
Atomy
Udostępnij dostęp do zmiennego stanu dla każdego wątku. Zmiana zachodzi synchronicznie. Spróbuj ponownie, gdy inny wątek zmieni stan podczas uruchamiania.
Nie używaj funkcji nie idempotentnych i funkcji z długim czasem wykonywania
Agenci
Udostępnij dostęp do zmiennego stanu dla każdego wątku. Zmiana zachodzi asynchronicznie.
Nr ref
Refs działa podobnie do transakcji w bazie danych. Zapis i odczyt są chronione w dosync. Możesz operować na wielu referencjach bezpiecznych w transakcji.
I schemat blokowy, gdy używamy którego:
Proszę spojrzeć na obraz na stronie internetowej, ponieważ zawsze możliwe są aktualizacje.
Udzielenie pełnej odpowiedzi bez kopiowania i poprzedniego artykułu jest złożonym i długim tematem, więc wybaczcie mi, że przekierowuję na stronę internetową :)
atomy, referencje i agenci - trochę oświetlenia tutaj http://blog.jayfields.com/2011/04/clojure-state-management.html
state-a
, ale odnosić się dostate-b
tego, nadal potrzebujęref
poprawnego? Czyli nie zmienia wielu rzeczy, ale odnosi się do wielu rzeczy, zmieniając dowolną z nich?