Question

Disons que vous avez la classe suivante

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

et vous exécutez le code suivant

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

Dans la dernière ligne while (!stats.compareAndSet(prev, newValue)) comment la méthode compareAndSet déterminer l'égalité entre prev et newValue? Est-ce la classe AccessStatistics nécessaire pour mettre en œuvre une méthode de equals()? Sinon, pourquoi? Les Etats javadoc ce qui suit pour AtomicReference.compareAndSet

  

atomiquement définit la valeur à la valeur actualisée donnée si la valeur actuelle == la valeur attendue.

... mais cette affirmation semble très générale et les tutoriels que j'ai lu sur AtomicReference suggère jamais la mise en œuvre un signe égal () pour une classe enveloppé dans un AtomicReference.

Si les classes enveloppés dans AtomicReference sont nécessaires pour equals (), puis pour des objets plus complexes que AccessStatistics je pense qu'il peut être plus rapide de synchroniser des méthodes qui mettent à jour l'objet et ne pas utiliser AtomicReference.

Était-ce utile?

La solution

Il compare les refrerences exactement comme si vous aviez utilisé l'opérateur ==. Cela signifie que les références doivent être orientées vers la même instance. Object.equals () n'est pas utilisé.

Autres conseils

En fait, il fait pas comparer prev et nouvelleValeur!

Au contraire, il compare la valeur stockée dans les statistiques à prev et seulement lorsque ceux-ci sont les mêmes, il met à jour la valeur stockée dans les statistiques NouvelleValeur. Comme dit ci-dessus, il utilise l'opérateur égal (==) de le faire. Cela signifie que lorsque anly prev pointe vers le même objet que est stocké dans les statistiques seront les statistiques mises à jour.

Il vérifie simplement l'égalité de référence d'objet (aka ==), donc si référence d'objet détenu par AtomicReference avait changé après avoir obtenu la référence, il ne changera pas la référence, de sorte que vous devrez recommencer.

Voici quelques-uns du code source de AtomicReference. AtomicReference fait référence à une référence d'objet. Cette référence est une variable membre volatile dans l'instance de AtomicReference comme ci-dessous.

private volatile V value;

get () retourne simplement la dernière valeur de la variable (comme le font dans un volatiles "passe avant" de manière).

public final V get()

Voici la méthode la plus importante de AtomicReference.

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

La méthode compareAndSet (attendre, mise à jour) appelle la méthode compareAndSwapObject () de la classe dangereuse de Java. Cet appel de méthode de dangereux invoque l'appel d'origine, qui appelle une instruction unique au processeur. « Attendre » et « mettre à jour » chaque référence un objet.

Si et seulement si la variable membre instance AtomicReference « valeur » fait référence au même objet est appelé par « attendre », « mise à jour » est affecté à cette variable d'instance maintenant, et « vrai » est retourné. Ou bien, le faux est retourné. L'ensemble est fait atomiquement. Aucun autre thread ne peut intercepter entre les deux. Comme il est une seule opération de processeur (magie de l'architecture informatique moderne), il est souvent plus rapide que d'utiliser un bloc synchronisé. Mais rappelez-vous que lorsque plusieurs variables doivent être automatiquement mises à jour, AtomicReference ne sera pas utile.

Je voudrais ajouter un code de fonctionnement à part entière, qui peut être exécuté dans Eclipse. Il dégagerait beaucoup de confusion. Ici 22 utilisateurs (fils) MYTHE tentent de réserver 20 sièges. Voici l'extrait de code suivi du code complet.

extrait de code 22 utilisateurs tentent de réserver 20 sièges.

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

Ce qui suit est le lien github pour ceux qui veulent voir le code complet en cours d'exécution qui est petit et concis. https://github.com/sankar4git/atomicReference/blob/master/Solution. java

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top