10

Si accedo a un objeto dentro de un método sincronizado o bloque sincronizado, ¿todos los objetos en ese elemento accedido también están sincronizados?¿La sincronización de Java actualizará la caché completa, o solo el objeto en el que sincronicé?

Imagina que no un objeto Queue que tiene un sincronizado método add() y take(), aceptando y repartiendo el complejo objeto Thing. Thing tiene muchas listas con otros objetos diferentes.

Ahora imagen Hilo de Before crea Thing y pone algunos objetos existentes en Thing, modifica algunos de estos objetos y así sucesivamente. El subproceso Before agrega Thing a Queue. Un poco más tarde hilo After toma el Thing de Queue.

PREGUNTA: ¿Thing y todos sus hijos/subobjeto estarán en el mismo estado que Before los dejó en? Incluso si el hilo After estaba trabajando en uno de estos subelementos un poco antes? Debido a que la imagen del procesador para el hilo After aún podría tener algo de información en caché en ese subelemento (la dirección de ese subobjeto sigue siendo la misma). ¿Todo esto en caché se invalidaría solo al acceder al objeto padre Thing de forma sincronizada?

Por favor, no responda como usar la concurrencia libs, etc. Quiero entender lo que está pasando.

Respuesta

7

El concepto importante en el modelo de memoria de Java es el happens-before order. Los resultados de las acciones de escritura que ocurren -antes de son visibles para estas acciones de lectura. Otros resultados pueden ser visibles o no.

El suceder antes orden es inducida por orden de sincronización de acciones entre hilos de rosca, y por el orden natural de las acciones en los hilos individuales.

Si en Before se sincroniza en un objeto (p.su Queue), y hacer todas sus manipulaciones de Thing y sus "objetos parciales" dentro o antes de este bloque sincronizado, y After sincronizados en el mismo Queue y lee estos objetos en o después del bloque sincronizado, entonces todos esos cambios son visibles al After.

9

Si un hilo modifica una variable, no se garantiza que otro hilo vea los cambios excepto en los siguientes casos (bueno, al menos en los siguientes casos; no estoy 100% seguro si hay más):

  • el hilo modificante deja un bloque o método sincronizado; esto induce un flujo de la memoria caché de hilos (de la misma manera que un hilo que ingresa a un bloque o método sincronizado induce una actualización) - esto es lo que ocurre en su caso
  • la variable modificada se declara volatile o es una de las variables atómicas de java.util.concurrent.atomic
  • los acabados de hilos de modificación (esto también induce un color, del mismo modo el inicio de un hilo induce una actualización)

Así que si sincroniza como usted explicó, otros hilos verán todos los cambios.

+1

sí Lo sé, pero esa no era mi pregunta :-) La sincronización también debe afectar a los cachés del procesador, de modo que los cambios se transfieren a la memoria común, de eso es de lo que se trata mi pregunta. Sé que si accedes a una referencia sin pasar por un bloque sincronizado de varios hilos paralelos, todo se arruina. Pero se trata más de pasar cosas de un hilo a otro y de garantizar que la estructura de datos sigue siendo correcta. ¿Entiende lo que digo? –

+1

Vea la respuesta de Paulo. Bloquear subprocesos es solo un aspecto de la sincronización, la relación de pasar antes de (vaciar la caché) es tan importante, si no más. También es mucho más complicado de entender y las API no son claras sobre lo que sucede antes (por ejemplo, creo que SwingUtilities.invokeLater provoca un happening anterior, pero no estoy 100% seguro). Recomiendo Java Concurrency in Practice de Goetz et al. Ponen mucho énfasis en suceder antes. – toto2

+0

Gracias por vencer sin explicación ... @Franz: No era evidente para mí que preguntabas por el modelo de memoria. Déjame reconsiderar mi respuesta. – musiKk

Cuestiones relacionadas