El modelo de memoria de Java describe cómo los subprocesos en el lenguaje de programación de Java interactúan a través de la memoria. Junto con la descripción de la ejecución de código de un solo subproceso, el modelo de memoria proporciona la semántica del lenguaje de programación Java.
El modelo de memoria Java original, desarrollado en 1995, fue ampliamente percibido como roto, evitando muchas optimizaciones de tiempo de ejecución y no brindando garantías suficientemente sólidas para la seguridad del código. Se actualizó a través del Proceso de la comunidad de Java , como Java Specification Request 133 (JSR-133), que entró en vigor en 2004, para Tiger (Java 5.0) . [1] [2]
Contexto
La plataforma y el lenguaje de programación Java proporcionan capacidades de subprocesos . La sincronización entre subprocesos es notoriamente difícil para los desarrolladores; esta dificultad se agrava porque las aplicaciones Java pueden ejecutarse en una amplia gama de procesadores y sistemas operativos . Para poder sacar conclusiones sobre el comportamiento de un programa, los diseñadores de Java decidieron que tenían que definir claramente los posibles comportamientos de todos los programas Java.
En las plataformas modernas, el código con frecuencia no se ejecuta en el orden en que se escribió. Es reordenado por el compilador, el procesador y el subsistema de memoria para lograr el máximo rendimiento. En arquitecturas de multiprocesador , los procesadores individuales pueden tener sus propios cachés locales que no están sincronizados con la memoria principal. En general, no es deseable exigir que los subprocesos permanezcan perfectamente sincronizados entre sí porque esto sería demasiado costoso desde el punto de vista del rendimiento. Esto significa que en un momento dado, diferentes subprocesos pueden ver diferentes valores para los mismos datos compartidos.
En un entorno de un solo subproceso, es fácil razonar sobre la ejecución del código. El enfoque típico requiere que el sistema implemente la semántica como en serie para subprocesos individuales de forma aislada. Cuando se ejecuta un hilo individual, parecerá que todas las acciones tomadas por ese hilo ocurren en el orden en que aparecen en el programa, incluso si las acciones en sí ocurren fuera de orden.
Si un hilo ejecuta sus instrucciones fuera de orden, entonces otro hilo podría ver el hecho de que esas instrucciones se ejecutaron fuera de orden, incluso si eso no afectó la semántica del primer hilo. Por ejemplo, considere dos subprocesos con las siguientes instrucciones, ejecutándose simultáneamente, donde las variables xey se inicializan ambas en 0:
Hilo 1 | Hilo 2 |
---|---|
x = 1; | int r1 = y; |
y = 2; | int r2 = x; |
Si no se realizan reordenamientos y la lectura de y en el subproceso 2 devuelve el valor 2, la lectura posterior de x debe devolver el valor 1, porque la escritura en x se realizó antes de la escritura en y. Sin embargo, si las dos escrituras se reordenan, la lectura de y puede devolver el valor 2 y la lectura de x puede devolver el valor 0.
El modelo de memoria Java (JMM) define el comportamiento permisible de los programas multiproceso y, por lo tanto, describe cuándo son posibles tales reordenamientos. Establece restricciones de tiempo de ejecución en la relación entre los subprocesos y la memoria principal para lograr aplicaciones Java consistentes y confiables. Al hacer esto, hace posible razonar sobre la ejecución del código en un entorno multiproceso, incluso frente a las optimizaciones realizadas por el compilador dinámico, el (los) procesador (es) y las cachés.
El modelo de memoria
Para la ejecución de un solo hilo, las reglas son simples. La especificación del lenguaje Java requiere una máquina virtual Java para observar la semántica dentro del subproceso como si fuera en serie . El tiempo de ejecución (que, en este caso, generalmente se refiere al compilador dinámico, el procesador y el subsistema de memoria) es libre de introducir cualquier optimización de ejecución útil siempre que se garantice que el resultado del hilo de forma aislada sea exactamente el mismo que habría sido si todas las declaraciones se hubieran ejecutado en el orden en que ocurrieron en el programa (también llamado orden del programa). [3]
La principal advertencia de esto es que la semántica como-si-serial no evita que diferentes subprocesos tengan diferentes vistas de los datos. El modelo de memoria proporciona una guía clara sobre qué valores se pueden devolver cuando se leen los datos. Las reglas básicas implican que las acciones individuales se pueden reordenar, siempre y cuando no se viole la semántica como-si-serial del hilo, y las acciones que implican comunicación entre hilos, como la adquisición o liberación de un bloqueo , aseguran que las acciones que suceden antes que ellos son vistos por otros hilos que ven sus efectos. Por ejemplo, todo lo que ocurra antes del desbloqueo de un candado se verá ordenado antes y visible para todo lo que suceda después de una posterior adquisición de ese mismo candado. [4]
Matemáticamente, existe un orden parcial llamado orden de ocurre antes de todas las acciones realizadas por el programa. El orden de ocurre antes subsume el orden del programa; si una acción ocurre antes que otra en el orden del programa, ocurrirá antes que la otra en el orden que ocurre antes . Además, las liberaciones y adquisiciones posteriores de bloqueos forman bordes en el gráfico de eventos anteriores. Se permite que una lectura devuelva el valor de una escritura si esa escritura es la última escritura en esa variable antes de la lectura a lo largo de alguna ruta en el orden de pasa-antes , o si la escritura no está ordenada con respecto a esa lectura en el pasa- antes de la orden.
Impacto
El modelo de memoria de Java fue el primer intento de proporcionar un modelo de memoria completo para un lenguaje de programación popular. [5] Se justificó por la creciente prevalencia de sistemas concurrentes y paralelos, y la necesidad de proporcionar herramientas y tecnologías con semántica clara para tales sistemas. Desde entonces, la necesidad de un modelo de memoria ha sido más aceptada, con una semántica similar para lenguajes como C ++ . [6]
Ver también
Referencias
- ↑ Goetz, Brian (24 de febrero de 2004). "Arreglando el modelo de memoria de Java, Parte 2" (PDF) . Consultado el 18 de octubre de 2010 .
- ^ Jeremy Manson y Brian Goetz (febrero de 2004). "Preguntas frecuentes sobre JSR 133 (modelo de memoria Java)" . Consultado el 18 de octubre de 2010 .
El modelo de memoria de Java describe qué comportamientos son legales en código multiproceso y cómo los subprocesos pueden interactuar a través de la memoria. Describe la relación entre las variables en un programa y los detalles de bajo nivel para almacenarlas y recuperarlas desde y hacia la memoria o los registros en un sistema informático real. Lo hace de una manera que se puede implementar correctamente utilizando una amplia variedad de hardware y una amplia variedad de optimizaciones del compilador.
- ^ Manson, Jeremy. "Preguntas frecuentes sobre JSR-133" .
- ^ "JLS sucede antes de la orden" .
- ^ Goetz, Brian (24 de febrero de 2004). "Arreglando el modelo de memoria de Java, Parte 1" (PDF) . Consultado el 17 de febrero de 2008 .
- ^ Boehm, Hans. "Modelo de hilos y memoria para C ++" . Consultado el 8 de agosto de 2014 .
enlaces externos
- Teoría y práctica de Java: reparación del modelo de memoria de Java, parte 1 : artículo que describe problemas con el modelo de memoria de Java original.
- Teoría y práctica de Java: reparación del modelo de memoria de Java, parte 2 : explica los cambios que JSR 133 realizó en el modelo de memoria de Java.
- Pragmática del modelo de memoria de Java (transcripción)
- Los enlaces del modelo de memoria de Java
- Estructura interna de Java
- Página web JSR-133
- Preguntas frecuentes sobre JSR-133
- Guía de implementación de JSR-133