Pregunta ¿Por qué el código fuente JDK toma una copia `final` de instancias` volátiles`


Leí el código fuente del JDK sobre ConcurrentHashMap.

Pero el siguiente código me confundió:

public boolean isEmpty() {
    final Segment<K,V>[] segments = this.segments;
    ...
}

Mi pregunta es:

"this.segments" está declarado:

final Segment<K,V>[] segments;

Entonces, aquí, al comienzo del método, declaró una referencia de tipo similar, apuntando a la misma memoria.

¿Por qué el autor lo escribió así? ¿Por qué no usaron esto segmentos directamente? ¿Hay alguna razón?


74
2017-10-31 10:29


origen


Respuestas:


Esta es una expresión idiomática típica para el código sin bloque que involucra volatile variables. En la primera línea, lees el volatile una vez y luego trabajar con eso. Mientras tanto, otro hilo puede actualizar el volatile, pero solo le interesa el valor que inicialmente leyó.

Además, incluso cuando la variable miembro en cuestión no es volátil sino definitiva, esta expresión tiene que ver con las memorias caché de la CPU, ya que leer desde una ubicación de pila es más fácil de almacenar en caché que leer desde una ubicación de pila aleatoria. También hay una mayor probabilidad de que la var local termine ligada a un registro de CPU.

Para este último caso, en realidad hay cierta controversia, ya que el compilador de JIT generalmente se encargará de esas preocupaciones, pero Doug Lea es uno de los que lo sigue por principio general.


94
2017-10-31 10:31



Supongo que es para la consideración del rendimiento, por lo que solo necesitamos recuperar el valor del campo una vez.

Puede referirse a un idioma singleton de java efectivo por Joshua Bloch

Su singleton está aquí:

private volatile FieldType field;
FieldType getField() {
  FieldType result = field;
  if (result == null) { 
    synchronized(this) {
      result = field;
      if (result == null) 
        field = result = computeFieldValue();
    }
  }
  return result;
}

y él escribió:

Este código puede parecer un poco intrincado. En particular, la necesidad de   el resultado de la variable local puede ser poco claro. Lo que hace esta variable es   asegúrese de que el campo se lea solo una vez en el caso común donde está   ya inicializado Si bien no es estrictamente necesario, esto puede mejorar   rendimiento y es más elegante por los estándares aplicados a bajo nivel   programación concurrente. En mi máquina, el método anterior es de aproximadamente 25   por ciento más rápido que la versión obvia sin una variable local.


19
2017-10-31 10:52



Puede reducir el tamaño del código de bytes: el acceso a una variable local es más corto en el código de bytes que el acceso a una variable de instancia.

La sobrecarga de optimización del tiempo de ejecución también puede reducirse.

Pero ninguno de estos son significativos. Se trata más de estilo de código. Si te sientes cómodo con las variables de instancia, por supuesto. Doug Lea probablemente sensación un trato más cómodo con las variables locales.


4
2017-10-31 16:41