El modelo de memoria de Java (en inglés: Java memory model, JMM) describe cómo los hilos de ejecución en el lenguaje de programación Java interactúan a través de la memoria. Junto con la descripción de la ejecución monotarea, el modelo de memoria proporciona la semántica del lenguaje de programación Java.
Fue actualizado a través del Java Community Process como Java Specification Request 133 (JSR-133), que entró en vigor en 2004 para Tiger (Java 5.0).
Historia
El modelo de memoria original desarrollado en 1995 fue ampliamente percibido como defectuoso, impidiendo muchas optimizaciones en tiempo de ejecución y no proporcionando garantías lo suficientemente sólidas para la seguridad del código.Manson, Scott; Pugh, William (2004). "JSR-133: Java Memory Model and Thread Specification". Java Community Process.
El nuevo modelo de memoria definido en JSR-133 formaliza el comportamiento de los accesos a memoria compartida en programas Java multitarea, haciendo posible razonar sobre la ejecución del código en un entorno multitarea, incluso frente a las optimizaciones realizadas por el compilador dinámico, los procesadores y las cachés.
Definición formal
Un modelo de memoria describe, dado un programa y una traza de ejecución de ese programa, si la traza de ejecución es una ejecución legal del programa. El modelo de memoria del lenguaje Java examina cada lectura en una traza de ejecución y verifica que la escritura observada por esa lectura sea válida según ciertas reglas.
Una implementación es libre de producir cualquier código que desee, siempre que todas las ejecuciones resultantes de un programa produzcan un resultado que pueda ser predicho por el modelo de memoria.
Variables compartidas
La memoria que puede ser compartida entre hilos se denomina memoria compartida o memoria heap. Todos los campos de instancia, campos estáticos y elementos de array se almacenan en la memoria heap. Las variables locales, los parámetros formales de método y los parámetros de manejador de excepciones nunca se comparten entre hilos y no se ven afectadas por el modelo de memoria.
Dos accesos (lecturas o escrituras) a la misma variable se denominan conflictivos si al menos uno de los accesos es una escritura.
Acciones
Una acción inter-hilos es una acción realizada por un hilo que puede ser detectada o influenciada directamente por otro hilo. Los tipos principales son:
Lectura (normal o no volátil): leer una variable. Escritura (normal o no volátil): escribir una variable. Acciones de sincronización: Lectura volátil de una variable. Escritura volátil de una variable. Bloqueo (lock) de un monitor. Desbloqueo (unlock) de un monitor. La primera y última acción de un hilo.
Orden del programa
Entre todas las acciones inter-hilos realizadas por cada hilo , el orden del programa de es un orden total que refleja el orden en el que estas acciones se realizarían según la semántica intra-hilo de .
Un conjunto de acciones es secuencialmente consistente si todas las acciones ocurren en un orden total (el orden de ejecución) que es consistente con el orden del programa, y además, cada lectura de una variable ve el valor escrito por la escritura a tal que viene antes que en el orden de ejecución.
Orden de sincronización
Cada ejecución tiene un orden de sincronización, que es un orden total sobre todas las acciones de sincronización de una ejecución. Las acciones de sincronización inducen la relación sincronizado-con (synchronized-with) definida como:
Una acción de desbloqueo en un monitor se sincroniza-con todas las acciones de bloqueo posteriores en . Una escritura en una Variable volátil se sincroniza-con todas las lecturas posteriores de por cualquier hilo. Una acción que inicia un hilo se sincroniza-con la primera acción en el hilo que inicia. La acción final en un hilo se sincroniza-con cualquier acción en otro hilo que detecta que ha terminado.
Happens-before
Dos acciones pueden ser ordenadas por una relación happens-before (sucede-antes). Si una acción happens-before otra, entonces la primera es visible para y ordenada antes que la segunda.
Si tenemos dos acciones e , escribimos para indicar que happens-before :
Si e son acciones del mismo hilo y viene antes que en el orden del programa, entonces . Si una acción se sincroniza-con una acción siguiente , entonces también tenemos . Si y , entonces (transitividad).
Matemáticamente, existe un orden parcial llamado orden happens-before sobre todas las acciones realizadas por el programa. El orden happens-before 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 happens-before.
Carreras de datos
Cuando un programa contiene dos accesos conflictivos que no están ordenados por una relación happens-before, se dice que contiene una carrera de datos (data race).
Un programa está correctamente sincronizado si y solo si todas las ejecuciones secuencialmente consistentes están libres de carreras de datos. Si un programa está correctamente sincronizado, entonces todas las ejecuciones del programa aparecerán como secuencialmente consistentes.
Semántica as-if-serial
Para la ejecución de un solo hilo, la Java Language Specification requiere que una máquina virtual Java observe la semántica as-if-serial (como si fuera en serie). El entorno de ejecución (compilador dinámico, procesador y subsistema de memoria) es libre de introducir cualquier optimización de ejecución útil siempre que el resultado del hilo aislado sea exactamente el mismo que si todas las sentencias se hubieran ejecutado en el orden en que aparecen en el programa.
Véase también Máquina virtual de Java Concurrencia (informática) Hilo de ejecución Sincronización (informática) Variable volátil
Referencias
Categoría:Plataforma Java