Frage

Ich versuche, Clojure von den API und Dokumentation auf der Website zu erfahren. Ich bin ein wenig unklar, wandelbar Lagerung in Clojure und ich möchte sicherstellen, dass mein Verständnis korrekt ist. Bitte lassen Sie mich wissen, ob es irgendwelche Ideen, die ich falsch bekommen haben.

Edit:. Ich bin Aktualisierung dieser, wie ich Kommentare auf ihre Richtigkeit erhalten


Haftungsausschluss: Alle diese Informationen ist informell und möglicherweise falsch. Verpassen Sie nicht diese Post verwenden, um zu gewinnen ein Verständnis dafür, wie Clojure funktioniert.


Vars enthalten immer eine Root-Bindung und gegebenenfalls eine Bindung pro Thread. Sie sind vergleichbar mit regulären Variablen in imperativen Sprachen und sind nicht für den Austausch von Informationen zwischen den Threads geeignet. (Dank Arthur Ulfeldt)

Refs sind Positionen geteilt zwischen Threads, die atomaren Transaktionen unterstützen, die den Zustand von einem beliebigen Anzahl von Druckschriften in einer einzigen Transaktion ändern. Transaktionen sind verpflichtet, auf sync Ausdrücke verlass (DoSync) und Konflikte gelöst werden automatisch mit STM Magie (Rollbacks, Warteschlangen wartet, usw.)

Agenten sind Orte, die Informationen ermöglichen asynchron durch Dispatching unabhängige Aktionsfunktionen zwischen Threads mit minimalem Aufwand geteilt wird der Status des Agenten zu ändern. Agenten werden sofort zurückgegeben und sind daher nicht blockierend, obwohl ein Wert des Agenten nicht gesetzt ist, bis eine versandt Funktion abgeschlossen hat.

Atome sind Orte, die synchron zwischen Threads gemeinsam genutzt werden kann. Sie unterstützen sichere Manipulation zwischen verschiedenen Threads.

Hier ist meine freundliche Zusammenfassung basiert auf, wenn diese Strukturen verwenden:

  • Vars sind wie normale alte Variablen in imperativen Sprachen. (Vermeiden, wenn möglich)
  • Atome sind wie Vars aber mit Thread-Sharing Sicherheit, die für die sofortige Lesen und sichere Einstellung ermöglicht. (Danke Martin)
  • Ein Agent ist wie ein Atom, sondern als Blockierung erzeugt er einen neuen Thread seinen Wert zu berechnen, nur wenige Blocks, wenn in der Mitte einen Wert zu ändern, und können andere Threads wissen lassen, dass es fertig zuweisen.
  • Refs sind Stellen geteilt, die sich in Transaktionen sperren. Stattdessen macht die Programmierer entscheiden, was für jedes Stück gesperrten Code während der Rennbedingung passiert, wir nur eine Transaktion starten und lassen Sie Clojure zwischen dem Refs in dieser Transaktion alle Verriegelungsbedingungen behandeln.

Auch ein verwandtes Konzept ist die Funktion future. Für mich scheint es wie ein künftiges Objekt kann als Synchronstelle beschrieben, in dem der Wert kann nicht zugegriffen werden, bis die Berechnung abgeschlossen ist. Es kann auch als nicht-blockierend Atom beschrieben. Sind diese genauen Vorstellungen von Zukunft?

War es hilfreich?

Lösung

Es klingt wie Sie sind wirklich immer Clojure! gute Arbeit:)

Vars haben eine „root binding“ sichtbar in allen Threads und jeder einzelne Faden kann den Wert, den es mit sich verändern sieht die anderen Threads zu beeinflussen. Wenn mein Verständnis korrekt ein var existieren kann nicht aus einer Wurzel in nur einem Thread ist verbindlich, ist für alle sichtbar und es kann nicht „Rebound“, bis es mit (def ...) erstmals definiert wurde.

Refs sind am Ende der (DoSync ...) Transaktion verpflichtet, die Änderungen umschließt, aber nur, wenn die Transaktion der Lage war, in einem konsistenten Zustand zu beenden.

Andere Tipps

Ich denke, Ihre Aussage über Atom ist falsch:

  

Atome sind wie Vars aber mit Gewinde-Sharing-Sicherheit blockiert, bis der Wert hat sich geändert

Atome werden mit swap! oder Low-Level mit compare-and-set! geändert. Diese nie blockiert alles. swap! funktioniert wie eine Transaktion mit nur einem ref:

  1. wird der alte Wert aus dem Atom, und Thread-local
  2. gespeichert
  3. die Funktion auf den alten Wert angewandt wird, um einen neuen Wert zu generieren
  4. wenn dies gelingt Vergleichs- und eingestellt ist mit alten und neuen Wert genannt; nur dann, wenn der Wert des Atoms hat nicht von einem anderen Thread (noch gleich alten Wert), der neue Wert wird geschrieben, andernfalls wird der Betrieb startet bei (1) bis heißt gelingt schließlich geändert.

Ich habe zwei Probleme mit Ihrer Frage gefunden.

Sie sagen:

  

Wenn ein Agent zugegriffen wird, während eine Aktion auftritt, dann wird der Wert nicht zurückgegeben, bis die Aktion abgeschlossen ist

http://clojure.org/agents sagt:

  

der Zustand eines Agenten ist immer sofort verfügbar von jedem Thread zum Lesen

d. Sie haben nie den Wert eines Agenten warten, um (I den Wert annehmen, geändert wird atomar durch eine Aktion proxied und geändert).

Der Code für die deref-Methode eines Agent sieht wie folgt aus (SVN Revision 1382):

public Object deref() throws Exception{
    if(errors != null)
    {
        throw new Exception("Agent has errors", (Exception) RT.first(errors));
    }
return state;

}

Keine Blockade beteiligt ist.

Auch verstehe ich nicht, was Sie (in Ihrem Ref Abschnitt) bedeuten durch

  

Die Transaktionen werden auf Anrufe verpflichtet deref

Transaktionen begangen werden, wenn alle Aktionen des DoSync Block abgeschlossen wurden, wurden keine Ausnahmen geworfen und nichts, um die Transaktion erneut versucht zu werden, verursacht hat. Ich denke, deref nichts damit zu tun hat, aber vielleicht habe ich falsch verstehen Ihren Punkt.

Martin hat recht, wenn er sagt, dass Atome Betrieb bei 1 startet, bis schließlich gelingt. Es wird auch Spin Warte genannt. Während es blockiert Note wirklich auf einer Sperre den Faden, der die Operation tat, bis der Vorgang blockiert gelingt so ist es ein Sperrbetrieb und nicht ein asynchron Betrieb.

Auch über Futures, Clojure 1.1 hat Abstraktionen für Versprechungen und Futures hinzugefügt. Ein Wort ist ein Synchronisations-Konstrukt, das verwendet werden kann, einen Wert von einem Thread zu einem anderen zu liefern. Bis der Wert geliefert wurde, wird jeder Versuch, dereferenzieren das Versprechen blockiert.

(def a-promise (promise))
(deliver a-promise :fred)

Futures repräsentieren asynchrone Berechnungen. Sie sind ein Weg, um Code zu bekommen in einem anderen Thread ausgeführt werden, und erhält das Ergebnis aus.

(def f (future (some-sexp)))
(deref f) ; blocks the thread that derefs f until value is available

Vars haben nicht immer eine Wurzel zu binden. Es ist legal eine var ohne eine Bindung mit

zu erstellen
(def x)

oder

(declare x)

Der Versuch x zu bewerten, bevor sie einen Wert hat, wird in Folge

Var user/x is unbound.
[Thrown class java.lang.IllegalStateException]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top