2012-04-24 22 views
5

que tienen un elemento de la clase¿Es esta una publicación segura del objeto?

class Item { 
    public int count; 
    public Item(int count) { 
    this.count = count; 
    } 
} 

A continuación, voy a poner una referencia al artículo en un campo de otra clase

class Holder { 
    public Item item; 
    public Holder() { 
    item = new Item(50); 
    } 
} 

Puede este nuevo objeto artículo se publicará de forma segura? Si no, ¿por qué? Según Java Concurrency in Practice, el nuevo artículo se publica sin estar completamente construido, pero en mi opinión el nuevo ítem está completamente construido: su referencia this no se escapa y la referencia a este y su estado se publica al mismo hora, por lo que el hilo del consumidor no verá un valor obsoleto. ¿O es el problema de visibilidad? No sé exactamente el motivo.

+0

Interesante artículo de DW sobre el tema que explora muchos de los problemas relacionados con la sincronización: http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html – maksimov

+0

Lo siento mucho, lo he olvidado! – ohyeahchenzai

Respuesta

13

¿Se puede publicar con seguridad este nuevo objeto? Si no, ¿por qué?

El problema gira en torno a las optimizaciones y el reordenamiento de las instrucciones. Cuando se tienen dos hilos que están usando un objeto construido sin sincronización, puede ocurrir que el compilador decide cambiar el orden de las instrucciones por causa eficiencia y asignar el espacio de memoria para un objeto y almacenar su referencia en el campo item antes termina con el constructor y la inicialización de campo. O puede reordenar la sincronización de memoria para que otros hilos perciban de esa manera.

Si marca el campo item como final, entonces se garantiza que el constructor finalizará la inicialización de ese campo como parte del constructor. De lo contrario, deberá sincronizar en un candado antes de usarlo. Esto es parte de Java language definition.

Aquí hay otro par de referencias:

+0

Tal vez debería leer la especificación del lenguaje Java, ¡gracias! – ohyeahchenzai

+0

Permítanme señalarles directamente el [capítulo.] Correcto (http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4) Es una gran lectura, mucho más que solo especificación seca. –

+0

Gracias @Marko. He agregado ese enlace a mi respuesta. – Gray

5

Sí, hay un problema de visibilidad, como Holder.item no es final. Por lo tanto, no hay garantía de que otro subproceso verá su valor inicializado una vez finalizada la construcción de Holder.

Y como señaló @Gray, la JVM puede reordenar instrucciones en ausencia de barreras de memoria (que pueden crearse mediante un bloqueo (sincronización), un calificador final o volatile). Dependiendo del contexto, debe usar uno de estos aquí para garantizar una publicación segura.

+0

Creo que puedo obtener la respuesta, es el reordenamiento, pero no el orden exacto que puede tomar, pero como Gray lo señaló, sé algo al respecto, ¡gracias a los dos! – ohyeahchenzai

+0

@ohyeahchenzai Si estudia cuidadosamente el capítulo si JLS lo menciona en la otra respuesta, todo estará claro para usted. –

+0

Otra buena razón para favorecer la inmutabilidad haciendo que los campos sean definitivos. –

Cuestiones relacionadas