initialize how ejemplo concurrent atomicinteger java concurrency int

java - how - ¿Esto es técnicamente seguro para hilos a pesar de ser mutable?



java concurrent collections (1)

Sí, la bar variables miembro privada debe ser la final ¿no? Pero en realidad, en este caso, es una operación atómica simplemente leer el valor de un int . Entonces, ¿esto es técnicamente seguro para hilos?

class Foo { private int bar; public Foo(int bar) { this.bar = bar; } public int getBar() { return bar; } }

// supongamos que un número infinito de hilos llama repetidamente a getBar en la misma instancia de Foo .

EDITAR:

Supongamos que esto es todo el código para la clase Foo ; cualquier hilo con una referencia a una instancia de Foo no podrá cambiar el valor de la bar (sin llegar a longitudes tales como usar la reflexión, etc.)


Actualización final: así que mi primera conclusión resultó ser correcta, solo mi razonamiento era defectuoso :-( Reedite mi respuesta para que sea algo coherente, no para ocultar las huellas de mi anterior error.

Conclusión

Como señaló @Wyzard, a pesar de que no hay forma de cambiar la bar después de la construcción, Foo aún no es seguro para subprocesos. El problema no es la atomicidad, sino la visibilidad. Si el hilo 1 está cambiando el valor de la bar en el constructor (desde su valor predeterminado de 0), no hay garantía de que otros hilos vean el nuevo valor (o si lo ven).

Así que foo parece un objeto inmutable. Citando de Java Concurrency in Practice , sección 3.4:

Un objeto es inmutable si:

  • Su estado no se puede modificar después de la construcción;
  • Todos sus campos son finales; y
  • Está construido correctamente (esta referencia no se escapa durante la construcción).

Foo ve bien en 1) y 3), pero no en 2). Y ese es un punto crucial, debido al razonamiento anterior. Declarar una variable final es una forma de garantizar su visibilidad entre diferentes hilos. Los otros medios están declarando la bar volatile o sincronizando sus métodos de acceso. Pero, por supuesto, en el caso de un objeto inmutable, ninguno de estos tendría mucho sentido.

Campos finales

Entonces, ¿por qué los campos final garantizan la visibilidad? Respuesta de Java Concurrency in Practice, sección 3.5.2:

Debido a que los objetos inmutables son tan importantes, el Modelo JavaMemory ofrece una garantía especial de seguridad de inicialización para compartir objetos inmutables. Como hemos visto, que una referencia de objeto sea visible para otro hilo no significa necesariamente que el estado de ese objeto sea visible para el hilo consumidor. Para garantizar una vista coherente del estado del objeto, se necesita sincronización.

Los objetos inmutables, por otro lado, se pueden acceder con seguridad incluso cuando la sincronización no se usa para publicar la referencia del objeto . Para que se garantice la seguridad de la inicialización, deben cumplirse todos los requisitos de inmutabilidad: estado no modificable, todos los campos son definitivos y deben construirse correctamente. [...]

Los objetos inmutables se pueden usar con seguridad mediante cualquier hilo sin sincronización adicional, incluso cuando la sincronización no se utiliza para publicarlos.

Esta garantía se extiende a los valores de todos los campos finales de objetos construidos correctamente; los campos finales se pueden acceder de forma segura sin sincronización adicional. Sin embargo, si los campos finales se refieren a objetos mutables, aún se requiere sincronización para acceder al estado de los objetos a los que hacen referencia.

¿Y qué pasa si el campo no es final? Otros subprocesos pueden ver silenciosamente un valor obsoleto del campo. No hay excepción ni ningún tipo de advertencia: esa es una razón por la cual estos tipos de errores son tan difíciles de rastrear.