Pregunta

Supongamos que tiene la siguiente clase

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

y ejecutar el siguiente código

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

En la última línea while (!stats.compareAndSet(prev, newValue)) cómo el método compareAndSet determinar la igualdad entre prev y newValue? Es la clase AccessStatistics necesario para implementar un método equals()? Si no es así, ¿por qué? Los estados javadoc lo siguiente para AtomicReference.compareAndSet

  

Atómicamente establece el valor en el valor actualizado determinado si el valor actual == el valor esperado.

... pero esta afirmación parece muy general y los tutoriales que he leído en AtomicReference nunca se sugiere la implementación de un signo igual () para una clase envuelta en una AtomicReference.

Si se requieren clases envueltas en AtomicReference implementar equals () y luego para los objetos más complejos que AccessStatistics estoy pensando que puede ser más rápido para sincronizar los métodos que actualizan el objeto y no utilizar AtomicReference.

¿Fue útil?

Solución

Se comparan los refrerences exactamente como si se hubiera usado el operador ==. Eso significa que las referencias deben estar apuntando a la misma instancia. Object.equals () no se utiliza.

Otros consejos

En realidad, lo hace no y comparar prev nuevoValor!

En su lugar, se compara el valor almacenado dentro de las estadísticas para Prev y sólo cuando estos son el mismo, se actualiza el valor almacenado dentro de las estadísticas a nuevoValor. Como se dijo anteriormente que utiliza el operador igual (==) para hacerlo. Esto significa que anly cuando prev está apuntando al mismo objeto que se almacena en las Estadísticas se actualizan las estadísticas.

Simplemente comprueba la igualdad de referencia de objeto (también conocido como ==), por lo que si referencia de objeto en poder de AtomicReference había cambiado después de que tienes la referencia, no va a cambiar la referencia, por lo que tendrá que empezar de nuevo.

A continuación se presentan algunos de los códigos fuente de AtomicReference. AtomicReference se refiere a una referencia de objeto. Esta referencia es una variable miembro volátil en la instancia AtomicReference como a continuación.

private volatile V value;

get () simplemente devuelve el último valor de la variable (como volátiles hacen en un "ocurre antes de" manera).

public final V get()

El siguiente es el método más importante de AtomicReference.

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

El compareAndSet (esperar, actualización) llama al método compareAndSwapObject () de la clase insegura de Java. Esta llamada a un método de insegura invoca la llamada nativa, que invoca una sola instrucción al procesador. "Espera" y "actualizar" cada referencia de un objeto.

Si y sólo si el miembro variable "valor" instancia AtomicReference se refiere al mismo objeto que se conoce por "esperar", "actualización" se asigna a esta variable de instancia ahora, y "verdadero" se devuelve. O de lo contrario, se devuelve false. Todo esto se hace automáticamente. Ningún otro hilo puede interceptar en el medio. Como se trata de una sola operación de procesador (magia de la arquitectura moderna de computadora), a menudo es más rápido que el uso de un bloque sincronizado. Pero recuerde que cuando múltiples variables necesitan ser actualizados de forma atómica, AtomicReference no ayudará.

Me gustaría añadir un código en ejecución de pleno derecho, que se puede ejecutar en Eclipse. Sería despejar muchas confusiones. Aquí 22 usuarios (hilos mito) están tratando de reservar 20 escaños. Lo que sigue es el fragmento de código seguido del código completo.

Fragmento de código donde 22 usuarios están tratando de reservar 20 escaños.

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

A continuación se presenta el enlace github para aquellos que quieran ver el código completo en la conducción que es pequeño y conciso. https://github.com/sankar4git/atomicReference/blob/master/Solution. java

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top