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);
}
¿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. –
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