En ArrayBlockingQueue, ¿por qué copiar campo último miembro en última variable local?
-
03-10-2019 - |
Pregunta
En ArrayBlockingQueue
, todos los métodos que requieren el bloqueo de la copian a una variable final
local antes de llamar lock()
.
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
insert(e);
return true;
}
} finally {
lock.unlock();
}
}
¿Hay alguna razón para copiar this.lock
a un lock
variable local cuando el campo es this.lock
final
?
Además, también se utiliza una copia local de E[]
antes de actuar en él:
private E extract() {
final E[] items = this.items;
E x = items[takeIndex];
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
notFull.signal();
return x;
}
¿Hay alguna razón para copiar un campo final a una última variable local?
Solución
Es una optimización extrema Doug Lea, el autor de la clase, le gusta usar. Aquí hay un post en una reciente hilo en la lista de correo de núcleo-libs-dev sobre este tema exacto que responde a su pregunta bastante bien.
del poste:
... copiar a la población local produce la más pequeña código de bytes, y por código de bajo nivel que es agradable escribir código Eso es un poco más cerca de la máquina
Otros consejos
Este hilo da algunas respuestas. En sustancia:
- el compilador no puede demostrar fácilmente que un campo final no cambia dentro de un método (debido a la reflexión / serialización etc.)
- compiladores más actuales en realidad no tratar y por lo tanto tiene que recargar la cada campo final se utiliza lo que podría conducir a un fallo de caché o un fallo de página
- almacenándolo en una de las fuerzas variables locales de la JVM para llevar a cabo una sola carga