2010-09-07 15 views
13

Tengo un bean simple @Entity Message.java que tiene algunas propiedades normales. El ciclo de vida de ese objeto es el siguiente¿Necesito sincronización adicional cuando uso un BlockingQueue?

instanciación del mensaje que pasa en Tema A, que se pone en cola después en un blockingQueue

Otro hilo de una piscina obtiene ese objeto y hacer algunas cosas con él y cambia el estado del mensaje, después de eso, el objeto ingresa nuevamente en la cola bloqueante. Este paso se repite hasta que una condición lo detiene. Cada vez que el objeto obtiene lectura/escritura es potencialmente de un hilo diferente, pero con la garantía de que solo un hilo a la vez le leerá/escribirá.

Dado que las circunstancias, ¿necesito sincronizar los getters/setters? ¿Quizás las propiedades sean volátiles? o puedo simplemente irme sin sincronización?

Gracias y espero que pueda aclarar lo que estoy teniendo aquí.

Respuesta

25

No, no necesita sincronizar el acceso a las propiedades del objeto, o incluso usar volatile en las variables miembro.

Todas las acciones realizadas por un hilo antes de poner en cola un objeto en un BlockingQueue "suceder antes", el objeto se quita de la cola. Eso significa que cualquier cambio hecho por el primer hilo es visible para el segundo. Este es un comportamiento común para colecciones concurrentes. Consulte el último párrafo de the BlockingQueue class documentation.

Siempre que el primer hilo no realice ninguna modificación después de poner en cola el objeto, será seguro.

+2

+1 por mencionar la semántica de visibilidad de subprocesos de BlockingQueue. – Darron

2

Si está seguro de que solo un hilo a la vez tendrá acceso a su objeto, entonces no necesita sincronización.

Sin embargo, puede asegurarse de que mediante el uso de la palabra clave sincronizada: cada vez que desee acceder a este objeto y asegúrese de que ningún otro hilo está utilizando la misma instancia, envuelva su código en un bloque sincronizado:

Message myMessage = // ... 
synchronized (myMessage) { 
    // You're the only one to have access to this instance, do what you want 
} 

El bloque sincronizado adquirirá un bloqueo implícito en el objeto myMessage. Entonces, ningún otro bloque sincronizado tendrá acceso a la misma instancia hasta que salga de este bloque.

+0

Sincronizar getters y setters individuales realmente no prueba nada si dos threads se entrelazan realmente en el objeto. Todavía lo verán en estados inconsistentes/hacer sobrescrituras parciales. Esta respuesta es la mejor manera de abordar el problema. – Affe

+0

@Vivien_Barousse así que, en realidad, no necesito sincronizar nada porque no se accederá al mismo tiempo. Esto responde mi pregunta, ¡gracias! –

3

No necesita hacer la sincronización usted mismo, porque la cola ya lo hace por usted.

La visibilidad también está garantizada.

0

Parece que podría salir de la sincronización de los métodos. El sincronizado simplemente bloquea el objeto para permitir que solo un hilo lo acceda. Ya has manejado eso con la cola de bloqueo.

Volatile sería bueno de usar, ya que eso garantizaría que cada hilo tenga la última versión, en lugar de un valor de caché local de subprocesos.

+0

El uso de 'volátil' con un' BlockingQueue' es innecesario (y una duplicación ineficiente de esfuerzo); parte del contrato 'BlockingQueue' es que cualquier acción de un hilo antes de poner en cola un objeto" sucede antes que "el objeto es quitado de la cola por otro hilo. – erickson

+0

Bueno saber. Sabía que era necesario volátil cuando otro hilo cambia el valor de un campo. Tiene sentido que el hilo de bloqueo cuide de eso, ya que el hilo actual solicita el valor. – tylermac

Cuestiones relacionadas