2011-08-22 11 views
6

¿Deberían ser todos los campos, incluidos los supercampos, de una clase java intencionalmente inmutable 'final' para ser seguro para subprocesos o es suficiente sin métodos modificadores?campos finales y seguridad de hilos

Supongamos que tengo un POJO con campos no finales donde todos los campos son del tipo de alguna clase inmutable. Este POJO tiene getters-setters, y un constructor que establece un valor inicial. Si extiendo este POJO con métodos de modificación de modificador, por lo que es inmutable, ¿será la clase de extensión segura para subprocesos?

+2

¿Qué quiere decir con * métodos modificadores * métodos modificadores? Lanzando una excepción de todos los setters? Esto violaría [el principio de sustitución de Liskov] (http://en.wikipedia.org/wiki/Liskov_substitution_principle). Pero sí, esta clase ** sería ** segura para subprocesos. –

+0

Sí, lanzando una excepción de tiempo de ejecución o anulándolos con un cuerpo vacío tal vez con un poco de registro. Sé que está violando LSP. – pcjuzer

Respuesta

11

Para utilizar un objeto efectivamente inmutable sin campos final de forma segura, debe utilizar una de las expresiones de publicación segura cuando el objeto esté disponible para otros hilos después de la inicialización, de lo contrario estos hilos pueden ver el objeto parcialmente inicializado estado (de Java Concurrency in Practice):

  • Inicialización de una referencia de objeto desde un inicializador estático;
  • Almacenar una referencia en un campo volátil o AtomicReference;
  • Almacenar una referencia en un campo final de un objeto construido correctamente; o
  • Guardando una referencia en un campo que esté debidamente protegido por un candado.

campos Declarar de su objeto inmutable como final comunicados de esta restricción (es decir, se garantiza que si otros hilos ven una referencia al objeto, también ven sus final campos en estado totalmente inicializado). Sin embargo, en general, no garantiza que otros subprocesos puedan ver una referencia al objeto tan pronto como se publicó, por lo que es posible que aún necesite utilizar una publicación segura para garantizarlo.

Tenga en cuenta que si su objeto implementa una interfaz, se puede utilizar un método utilizado por Collections.unmodifiableList(), etc:

class ImmutableFooWrapper implements IFoo { 
    private final IFoo delegate; // final provides safe publication automatically 

    public ImmutableFooWrapper(IFoo delegate) { 
     this.delegate = delegate; 
    } 
    ... 
} 

public IFoo immutableFoo(IFoo foo) { 
    return new ImmutableFooWrapper(foo); 
} 
+0

Gracias por su respuesta detallada. Estaba pensando en la misma solución con el uso de delegado, pero siempre volví a la solución con la extensión, porque supongo que la referencia 'super' también es definitiva. ¿Qué extraño? – pcjuzer

+0

@pcjuzer: 'super' no tiene nada que ver con la simultaneidad, por lo que en el caso de la extensión necesitaría una publicación segura de todos modos. – axtavt

+0

Entonces, eso significa que si está declarando un campo final, entonces si está siendo actualizado por un hilo, entonces otro hilo no lo verá y, si lo ve, lo verá en estado actualizado. – AKS

-2

Sí, será inmutable y por lo tanto seguro para subprocesos, pero sólo el tiempo que los campos son privado.

+2

¿Por qué los campos deben ser privados en realidad? – xSNRG

Cuestiones relacionadas