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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top