Thread Caching y modelo de memoria Java

Estoy tratando de entender el modelo de memoria de Java y los hilos. Como he comprendido, cada hilo tiene una copia local de la memoria “principal”. Entonces, si un hilo intenta cambiar una variable int , por ejemplo, de algún objeto, almacena en caché la variable int y, si lo cambia, es posible que el otro hilo no vea el cambio. Pero, ¿y si los subprocesos almacenan en caché algún objeto en lugar de int? ¿Qué hilos lo almacenan en caché en este caso? Si un hilo almacena en caché una referencia a un objeto, ¿no está visible para otros hilos cualquier cambio en el estado del objeto? ¿Por qué?

Gracias de antemano

La CPU tiene diferentes cachés de nivel L1, L2, L3. Cada CPU (y también / may CPU Core) tiene su propio caché. Este caché almacena un conjunto mínimo de memoria principal (RAM) para el rendimiento.

  _______________ ______________ | CPU 1 | | CPU 2 | | _________ | | _________ | | | Level 1 | | | | Level 1 | | | | Cache | | | | Cache | | | | | | | | | | | |_________| | | |_________| | |_______________| |______________| | | | | | | | | _|_|______________|_|__ | | | MAIN MEMORY | |_______________________| Time Command CPU 1 (Cache) CPU 2 (Cache) Main Memory ------- ---------- ---------------- -------------- ------------- 1 --- --- --- x = 10 2 Read x (on cpu1) x = 10 --- x = 10 3 Write x <--20 (on cpu1) x = 20 --- x = 10 4 Read x (on cpu2) x = 20 x = 10 x = 10 5 put cache to Main mem x = 20 x = 10 x = 20 

Por ejemplo, orden de ejecución anterior, el valor de x es incorrecto en la CPU2. x valor ya modificado por la CPU1. Si la variable x se define como volátil, todas las operaciones de escritura se reflejarán en la memoria principal al instante.

Un hilo no tiene una copia local de la memoria. Parte de la memoria que el hilo lee / escribe podría ser de un caché, en lugar de la memoria principal. Las memorias caché no necesitan estar sincronizadas entre sí o en sincronización con la memoria principal. Entonces aquí es donde puedes observar inconsistencias.

Entonces, si un hilo intenta cambiar una variable int, por ejemplo, de algún objeto, almacena en caché la variable int y, si lo cambia, otro hilo podría no ver el cambio.

Eso es correcto. El modelo de memoria de Java se define en las reglas de pasar antes, por ejemplo, hay una regla de ocurrencia antes de una escritura volátil del campo xy una lectura volátil del campo x. Entonces, cuando se realiza una escritura, una lectura posterior verá el valor escrito.

Sin tal sucede antes de la relación, todas las apuestas están apagadas (también el reordenamiento de la instrucción puede complicar la vida cuando no ocurre nada antes de la regla).

Si el hilo almacena en caché una referencia a un objeto, ¿cualquier cambio en el estado del objeto tampoco es visible para otros hilos? ¿Por qué?

Podría ser visible … también podría no ser visible. Sin una regla de pasar antes, todas las apuestas son de. La razón es que, de lo contrario, no se permitirán muchas optimizaciones, como trucos de hardware para acelerar las cosas o trucos de comstackción. Y, por supuesto, mantener siempre la memoria sincronizada con la memoria caché reduciría el rendimiento.

Las CPU tienen múltiples cachés. Son estas cachés de hardware las que pueden tener copias inconsistentes de los datos. La razón por la que pueden ser inconsistentes es que mantener todo en consistencia puede ralentizar su código por un factor de 10 y arruinar cualquier beneficio que obtenga al tener múltiples hilos. Para obtener un rendimiento decente necesita ser selectivamente consistente. El Modelo de memoria de Java describe cuándo garantizará que los datos sean consistentes, pero en el caso más simple no.

Nota: esto no es solo un problema de CPU. Un campo que no tiene que ser coherente entre hilos puede incluirse en el código. Esto puede significar que si un hilo cambia el valor, otro hilo NUNCA podría ver este cambio, ya que se ha grabado en el código.

“Sin embargo, antes de que pueda escribir un código de subprocesos decente, realmente necesita estudiar más sobre las complejidades y sutilezas del código de subprocesos múltiples.

Cuando se trata de hilos, se garantiza muy poco.

¿Se imaginan los esgulps que pueden ocurrir cuando dos subprocesos diferentes tienen acceso a una sola instancia de una clase, ambos hilos invocan métodos en ese objeto … y esos métodos modifican el estado del objeto? … es demasiado aterrador incluso para visualizar “, de Sun Certified Programmer for Java 6, capítulo 9: Threads.

Mi amigo,

En Java, los hilos no almacenan en caché ningún objeto o variable, solo tienen una referencia a una instancia de un objeto . Hablar de la memoria caché de subprocesos es más como hablar de subprocesos de sistemas operativos … Java funciona de la misma manera en todos los SO, sin importar cómo se gestionen los subprocesos internamente, lo que difiere mucho dependiendo de los diferentes sistemas operativos.

Mira este código:

 AccountDanger r = new AccountDanger(); Thread one = new Thread(r): Thread two = new Thread(r); 

Como puede ver, en este caso los subprocesos tienen acceso a la misma instancia: r . Entonces, tendrá problemas de sincronización , seguro … no importa si hablamos de miembros nativos o de objetos , los hilos uno y dos tendrán acceso a todos los miembros de r (si son accesibles a través de scope o setters / getters) ) y leerán directamente los valores de r instancia. Esto es seguro incluso si no lo notas, lo que a veces es muy difícil.

Te recomiendo que leas acerca de los scopes de Java y la sincronización java , si deseas codificar aplicaciones multihilo.

Saludos,

Cada subproceso no tiene una copia local de memoria. Si una variable es visible (debido a su scope) a más de un hilo, cada hilo verá el mismo valor.

Sin embargo, los progtwigs de subprocesos múltiples deben tener mucho cuidado al compartir variables (memoria) porque es muy fácil introducir condiciones de carrera si no se tiene cuidado.