Frage

Sagen Sie bitte die folgende Klasse haben

public class AccessStatistics {
  private final int noPages, noErrors;
  public AccessStatistics(int noPages, int noErrors) {
    this.noPages = noPages;
    this.noErrors = noErrors;
  }
  public int getNoPages() { return noPages; }
  public int getNoErrors() { return noErrors; }
}

und Sie führen den folgenden Code

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));
}

In der letzten Zeile while (!stats.compareAndSet(prev, newValue)) wie funktioniert die compareAndSet Methode bestimmt Gleichheit zwischen prev und newValue? Ist die AccessStatistics Klasse erforderlich, um eine equals() Methode zu implementieren? Wenn nicht, warum? Die javadoc besagt Folgendes für AtomicReference.compareAndSet

  

Atomar setzt den Wert auf den angegebenen Wert aktualisiert, wenn der aktuelle Wert == der erwartete Wert.

... aber diese Behauptung scheint sehr allgemein gehalten und die Tutorials i auf AtomicReference gelesen habe vorschlägt nie in einem AtomicReference wickelte eine equals () für eine Klasse implementieren.

Wenn Klassen in AtomicReference gewickelt sind erforderlich equals zu implementieren () dann für Objekte komplexer als AccessStatistics Ich denke, es kann schnelle Methoden synchronisieren, um das Objekt zu aktualisieren und nicht AtomicReference verwenden.

War es hilfreich?

Lösung

Sie vergleicht die refrerences genau so, wie wenn Sie den Operator == verwendet hatten. Das bedeutet, dass die Verweise auf die gleiche Instanz gerichtet sein muss. Object.equals () nicht verwendet wird.

Andere Tipps

Eigentlich tut es nicht vergleichen zurück und newValue!

Stattdessen vergleicht er die in Statistiken gespeicherten Wert Prev und nur dann, wenn diejenigen, die gleichen sind, aktualisiert sie den Wert innerhalb der Statistiken zu newValue gespeichert. Wie oben erwähnt verwendet es den Gleichheitsoperator (==), dies zu tun. Dies bedeutet, dass anly wenn i.Vj. auf das gleiche Objekt zeigt, wie in Statistiken gespeichert werden Statistiken aktualisiert werden.

Es prüft nur die Objektreferenz Gleichheit (aka ==), also wenn Objektverweis von AtomicReference gehalten geändert hatte, nachdem Sie den Verweis bekamen, wird es nicht die Referenz ändern, so dass Sie von vorne beginnen zu werden.

Im Folgenden sind einige der Quellcode AtomicReference. AtomicReference bezieht sich auf eine Objektreferenz. Diese Referenz ist ein flüchtiges Elementvariable in dem AtomicReference Beispiel wie unten.

private volatile V value;

get () gibt einfach den aktuellen Wert der Variablen (als flüchtige Bestandteile in einem tun „geschieht vor“ Art und Weise).

public final V get()

Im Folgenden ist die wichtigste Methode der AtomicReference.

public final boolean  compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

Die compareAndSet (erwarten, update) Methode ruft die compareAndSwapObject () -Methode der unsicheren Klasse von Java. Dieser Methodenaufruf unsicherer ruft den nativen Anruf, der einen einzelnen Befehl an den Prozessor aufruft. „Erwartet“ und „Update“ jeweils ein Objekt verweisen.

Wenn und nur wenn der AtomicReference Instanz Membervariable „Wert“ auf das gleiche Objekt bezieht sich auf bezeichnet durch „erwarten“, „update“ zugeordnet ist auf diese Instanz Variable jetzt, und „true“ zurückgegeben. Oder sonst wird false zurückgegeben. Das Ganze ist atomar getan. Kein anderer Thread kann abfangen dazwischen. Da dies ein Einzelprozessorbetrieb (Magie der modernen Computer-Architektur) ist, ist es oft schneller als ein synchronisiertes Block verwenden. Aber denken Sie daran, dass, wenn mehrere Variablen müssen atomar aktualisiert werden, AtomicReference wird nicht helfen.

Ich möchte einen vollwertigen Laufcode hinzufügen, die in Eclipse ausgeführt werden kann. Es würde viel Verwirrung löscht. Hier 22 Benutzer (Myth Threads) versuchen, 20 Sitze zu buchen. Im Anschluss an dem durch den vollständigen Code gefolgt Code-Schnipsel.

Code-Schnipsel, wo 22 Benutzer 20 Plätze buchen möchten.

for (int i = 0; i < 20; i++) {// 20 seats
            seats.add(new AtomicReference<Integer>());
        }
        Thread[] ths = new Thread[22];// 22 users
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new MyTh(seats, i);
            ths[i].start();
        }

Im Anschluss an die Github Link für diejenigen, die den laufenden vollständigen Code sehen will, die klein und prägnant ist. https://github.com/sankar4git/atomicReference/blob/master/Solution. java

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top