Porque es definitiva, sí. Las variables finales tienen una semántica especial de seguridad de subprocesos, ya que se garantiza que otros subprocesos verán el campo final al menos en el estado en que se encontraba cuando finalizó su constructor.
Esto está en JLS 17.5, aunque el idioma es un poco denso. Esta semántica se introdujo en Java 1.5, en particular por JSR-133. Consulte esta página para obtener una discusión sin especificaciones de JSR-133 y sus diversas implicaciones.
Tenga en cuenta que si modifica la instancia después de su constructor, es decir no necesariamente seguro para hilos. En ese caso, debe tomar las precauciones de seguridad habituales del hilo para asegurarse de que suceda antes de los bordes.
Estoy bastante seguro (aunque no del todo 100%) de que el hecho de que solo un hilo haga la inicialización de clase es no un factor aquí. Es cierto que la clase solo se inicia con un subproceso, pero no creo que haya ningún caso específico: antes de que se establezcan los límites entre ese subproceso y cualquier otro subproceso que use la clase (que no sea el otro subproceso que no tenga que reiniciarse) la clase). Por lo tanto, sin la palabra clave final
, otro subproceso podría ver una instancia parcialmente construida del objeto. Los bordes específicos de happen-before que JMM define están en JLS 17.4.5, y la inicialización de clase no se encuentra allí.
sí, gracias. Gran respuesta – MyTitle
Creo que la razón más importante que la definitiva es que la inicialización de la clase (inicialización estática) debe estar sincronizada y protegida contra subprocesos. Usar la sincronización establece el hecho antes de ordenar. Consulte 12.4.2 (http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4.2) para obtener más detalles. – sjlee
@sjlee Es cierto que la inicialización requiere bloqueos, pero si el hilo A inicializa MyClass, y el hilo B aparece unos 5 minutos más tarde y utiliza MyClass, el hilo B no intentará inicializar MyClass (porque ya se ha inicializado). Eso significa que no obtendrá el bloqueo en 'MyClass.class', lo que significa que no hay relación de ocurrencia previa entre las acciones del subproceso A y el subproceso B. Si cada hilo se bloqueara en 'MyThread.class' cada vez que lo usara, nunca necesitaría establecer ninguna otra relación de sucede antes. – yshavit