Según Java Concurrency in Action si tenemos la siguiente clase:
public class Wrapper { private int num; public Wrapper(int num) { this.num = num; } public void assertCorrectness() { if (num != num) throw new AssertionError("This is false"); } }e inicializamos una instancia de esta clase y la publicamos de una manera no segura (a través de un campo público simple, por ejemplo), entonces el assertCorrectness() podría arrojar un AssertionError, si se llama desde otro hilo. En otras palabras, esto significa que otro subproceso podría ver una referencia actualizada a la instancia, pero el estado de la instancia en sí podría estar desactualizado (por lo que un subproceso puede ver que existe un objeto pero está en un estado parcialmente construido / inconsistente).
Por otro lado, se dice que publicar una instancia de esta clase a través de una referencia volátil se considera seguro. Sin embargo, entendí que volatile solo garantiza que cualquier subproceso siempre verá una versión actualizada de una referencia, pero no el estado del objeto al que se hace referencia. Entonces, podemos estar seguros de que si un subproceso asigna una nueva instancia de la clase Wrapper a un campo volátil, todos los demás subprocesos verán que la referencia se actualizó. Pero, ¿existe el riesgo de que aún vean un objeto en un estado inconsistente / parcialmente construido?
No, porque el uso de volatile establece una relación de "sucede antes". Sin él, se permiten varios reordenamientos y otras cosas, lo que hace posible el estado inconsistente, pero con él, la JVM debe brindarle el resultado esperado.
En este caso, volatile no se usa para los efectos de visibilidad (subprocesos que ven valores actualizados), sino para la publicación segura proporcionada por Happpens-before. Esta característica de volatile a menudo se omite cuando se explica su uso.
La respuesta anterior es correcta.
Solo tenga en cuenta que effectively immutable + safe publication comporta de manera poco intuitiva en algunos casos.
Por ejemplo:
Si
thread 1 publica de forma segura el objeto o en el thread 2thread 2 publica de manera insegura el objeto o en el thread 3 al final, el thread 3 puede ver el objeto o en un estado inconsistente
Ver [1] y [2]
también esto
Los objetos inmutables reales no tienen tales problemas.