AtomicReference
-
12-12-2019 - |
Frage
Ich habe einige Fragen zur AtomicReference.compareAndSet()-Methode. Laut Dokument hieß es:
Setzt den Wert atomar auf den angegebenen aktualisierten Wert, wenn der aktuelle Wert == der erwartete Wert ist.
Soweit ich weiß, ist das ==
Der Operator vergleicht die Adresse zweier Objekte. Wenn ja, wie funktioniert das in Beispielen wie diesem?
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
Woher weiß JVM in diesem Codeausschnitt, welche Felder von AccessStatistics
sind in der zu vergleichen compareAndSet()
?Tatsächlich frage ich mich nur, wie diese ganze Strategie funktioniert, wenn Java kein Überschreiben zulässt ==
überhaupt?Vielen Dank für jeden Kommentar!
Lösung
Woher weiß JVM, welche Felder von AccessStatistics im CompareAndSet() verglichen werden sollen?
Das ist nicht der Fall.Die Felder im Objekt werden nicht verglichen.Es ist nur ein Vergleich Referenz des Objekts, wie es in der Dokumentation steht.Genau so ist es AtomicReference
Klasse funktioniert.Wie Sie aus dem erwähnen Javadocs, es benutzt ==
und nicht die equals()
Methode.
Setzt den Wert atomar auf den angegebenen aktualisierten Wert, wenn der aktuelle Wert == der erwartete Wert ist.
Alle der Atomic*
Klassen haben ähnliche Funktionen.Damit können Sie Werte atomar festlegen und gleichzeitig sicherstellen, dass ein anderer Thread Ihren Wert nicht überschreibt.Mit compareAndSet(...)
Sie müssen die aktuelle Objektreferenz angeben, um sicherzustellen, dass die Aktualisierung wie erwartet erfolgt.
In Ihrem Codeausschnitt wird versucht, ein unveränderliches Zugriffsstatistikobjekt hinzuzufügen.Es ruft also den aktuellen Wert ab, addiert ihn dazu und speichert dann die neue Statistik in der Referenz.Wenn ein anderer Thread gespeichert ist es ist Statistiken zwischen dieser Zeit, dann die compareAndSet
gibt „false“ zurück, durchläuft eine Schleife und versucht es erneut.Dies löst Rennbedingungen, ohne dass eine vorhanden sein muss synchronized
Block.
Andere Tipps
Die JVM vergleicht die Felder überhaupt nicht.Es Nur vergleicht, ob es sich um dieselbe Referenz, denselben Zeiger im Speicher oder wie auch immer Sie ihn nennen möchten, handelt oder nicht.