Domanda

Diciamo che avete la seguente classe

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

e si esegue il seguente codice

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

Nell'ultima riga while (!stats.compareAndSet(prev, newValue)) come fa il metodo compareAndSet determinare l'uguaglianza tra il prev e newValue? È la classe AccessStatistics tenuto ad attuare un metodo equals()? Se no, perché? Gli stati Javadoc quanto segue per AtomicReference.compareAndSet

  

Atomicamente imposta il valore al valore dato aggiornato se il valore corrente == il valore atteso.

... ma questa affermazione sembra molto generale e il tutorial che ho letto su AtomicReference mai suggerire l'implementazione di un equals () per una classe avvolto in un AtomicReference.

Se le classi avvolti in AtomicReference sono tenuti ad implementare equals (), poi per gli oggetti più complessi di quanto AccessStatistics sto pensando che può essere più veloce per sincronizzare i metodi che aggiornano l'oggetto e non usare AtomicReference.

È stato utile?

Soluzione

E 'a confronto le refrerences esattamente come se si fosse usato l'operatore ==. Ciò significa che i riferimenti devono essere rivolte alla stessa istanza. Object.equalsQ () non viene utilizzato.

Altri suggerimenti

In realtà, lo fa non Confronto prev e newValue!

Invece si confronta il valore memorizzato all'interno di statistiche per prev e solo quando questi sono gli stessi, si aggiorna il valore memorizzato all'interno di statistiche per newValue. Come detto sopra si utilizza l'operatore uguale (==) per farlo. Ciò significa che quando anly prev punta verso lo stesso oggetto è memorizzato nella previsti verranno aggiornati previsti.

Si controlla semplicemente l'uguaglianza oggetto di riferimento (aka ==), quindi se riferimento a un oggetto tenuto da AtomicReference era cambiato dopo aver ottenuto il riferimento, non cambierà il riferimento, quindi dovrete ricominciare da capo.

In seguito sono parte del codice sorgente del AtomicReference. AtomicReference riferisce ad un riferimento all'oggetto. Questo riferimento è una variabile membro volatile nel caso AtomicReference come sotto.

private volatile V value;

get () restituisce semplicemente l'ultimo valore della variabile (come volatili fare una "accade prima" maniera).

public final V get()

Di seguito è riportato il metodo più importante di AtomicReference.

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

Il compareAndSet (aspettarsi, update) metodo chiama il metodo compareAndSwapObject () della classe non sicuro di Java. Questo metodo chiamata pericoloso richiama la chiamata nativo, che richiama una singola istruzione al processore. "Aspettano" e "aggiornare" ogni riferimento a un oggetto.

Se e solo se il membro variabile "valore" istanza AtomicReference riferisce allo stesso oggetto viene indicato da "aspettarsi", "aggiornamento" viene assegnato a questa variabile esempio ora, e "vero" viene restituito. Oppure, viene restituito false. Il tutto è fatto in modo atomico. Nessun altro thread può intercettare in mezzo. Poiché si tratta di una singola operazione processore (magia dell'architettura computer moderno), è spesso più veloce rispetto all'utilizzo di un blocco sincronizzato. Ma ricordate che quando più variabili devono essere aggiornati atomicamente, AtomicReference non aiuterà.

Vorrei aggiungere un codice in esecuzione a pieno titolo, che può essere eseguito in Eclipse. Sarebbe chiaro molti confusione. Qui 22 utenti (thread mito) stanno cercando di prenotare 20 posti. In seguito è il frammento di codice seguito dal codice completo.

Snippet di codice in cui 22 utenti stanno cercando di prenotare 20 posti.

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

In seguito è il legame github per chi vuole vedere il codice completo in esecuzione che è piccolo e conciso. https://github.com/sankar4git/atomicReference/blob/master/Solution. java

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top