La comprensión en profundidad del modelo de memoria de Java (a)

Categoría modelo de programación concurrente

En la programación concurrente, tenemos que abordar dos cuestiones fundamentales: la forma de comunicarse entre hilos y cómo sincronizar entre hilos (hilo aquí es la entidad ejecución concurrente activo). Que se refiere al mecanismo de comunicación para el intercambio de información entre los hilos. En el comando de programación, el mecanismo de comunicación entre dos hilos: la memoria compartida y paso de mensajes.

En el modelo de concurrencia de memoria compartida, el programa estatal común compartida entre los hilos entre el hilo por escrito - implícitamente comunicar un estado común leer la memoria. En la mensajería modelo de concurrencia, no hay hilo común entre el estado, debe ser explícitamente comunicarse mediante la transmisión de mensajes explícitos entre los hilos.

Se refiere a la orden relativo del mecanismo de sincronización entre el programa operativo para controlar la aparición de diferentes hilos. En el modelo de concurrencia de memoria compartida, se realiza la sincronización explícita. El programador debe especificar explícitamente un método o una pieza de código necesarios para realizar la exclusión mutua entre los hilos. En la mensajería de modelo de concurrencia, ya que por lo tanto debe se realiza el mensaje de transmisión antes de recibir el mensaje de sincronización implícita.

concurrencia Java utiliza un modelo de memoria compartida, la comunicación entre el hilo de Java siempre se lleva a cabo de manera implícita, todo el proceso de comunicación es completamente transparente para el programador. Si se escribe un programa multihilo los programadores de Java no entienden el mecanismo de trabajo de la comunicación entre hilos llevadas a cabo de manera implícita, es probable que encuentre todo tipo de problemas de visibilidad memoria extraños.

Resumen modelo de memoria de Java

En Java, todos los campos de instancia, los campos estáticos y elementos de la matriz almacenados en la memoria de pila, el montón de memoria compartida (como se usa en el presente documento, "variable compartida" se refiere a la generación de instancia plazo campos, campos estáticos y elementos de la matriz) entre los hilos. Las variables locales (variables locales), los métodos para definir los parámetros (especificación del lenguaje Java llama parámetros formales método) y los parámetros del controlador de excepciones (parámetros de gestión de excepciones) no son compartidos entre los hilos, que no tienen visibilidad de los problemas de memoria, ni al afectar modelo de memoria.

Las comunicaciones entre hilos es controlado por el modelo de memoria de Java Java (aquí referido como JMM), JMM determinar una rosca escrituras en variables compartidas visible cuando otro hilo. Desde un punto de vista abstracto, JMM define una relación abstracta entre el hilo y la memoria principal: la memoria principal (memoria principal), cada hilo tiene una memoria local privada (memoria local) compartida entre hilos de almacenamiento variable de , la memoria local se almacena una copia de la rosca para leer / escribir variables compartidas. JMM memoria local es un concepto abstracto, y no son reales. Cubre la memoria caché, buffer de escritura, registros y otras optimizaciones de hardware y compilador. diagrama abstracto de modelo de memoria de Java son los siguientes:

                     La comprensión en profundidad del modelo de memoria de Java (a) - básico

En la vista de mapa, entre los hilos A y B son como hilos puedan ser comunicados, debe pasar por los dos pasos siguientes:

  1. Variables En primer lugar, el hilo actualizado una memoria local compartida a ser eliminados a la memoria principal.
  2. A continuación, el hilo B a leer en la memoria principal antes de que el subproceso A ha actualizado la variable compartida.

Un diagrama esquemático para ilustrar por los dos pasos siguientes:

                     La comprensión en profundidad del modelo de memoria de Java (a) - básico

Como puede observarse, A y B tienen memoria local en la copia de la memoria principal de la variable x compartida. Suponiendo inicial, valores de x de estos tres memoria son 0. Un hilo, cuando se ejecuta, actualiza el valor de x (suponiendo un valor de 1) almacenada temporalmente en su propia memoria local en A. Cuando el hilo A y el hilo B requiere la comunicación, el hilo de un primer valor de x será el propietario de purgado a la memoria principal después de la modificación memoria local, el valor de x en este momento la memoria principal se convierte en la 1. Posteriormente, el hilo B a la memoria principal para leer el valor de x después de la actualización de hilo A, el valor de x en este momento la memoria local de la rosca B también se convierte en 1.

En general, estos dos pasos sustancialmente en el hilo de rosca A envía un mensaje a B, y el proceso de comunicación deben pasar por la memoria principal. JMM mediante el control de la interacción entre la memoria principal y la memoria local de cada hilo de rosca, para proporcionar visibilidad de garantía memoria programador de Java.

reordenando

Con el fin de mejorar el rendimiento cuando se ejecuta un programa, a menudo se pueden reordenar las instrucciones del compilador y del procesador. Reordenación de tres tipos:

  1. Compilador de reordenamiento de optimización. El compilador de programas de un solo subproceso sin cambiar la semántica de la premisa, se puede cambiar el orden de ejecución de la instrucción.
  2. reordenamiento ILP. Moderna procesadores emplean el paralelismo a nivel de instrucción (instrucción a nivel de paralelismo, ILP) para solapar la pluralidad de instrucciones ejecutadas. Si no existe ninguna dependencia de datos, el procesador puede cambiar la ejecución de instrucciones de la máquina correspondientes a la secuencia comunicado.
  3. Reordenación de la memoria del sistema. Puesto que el procesador utiliza la memoria caché y el / búfer de lectura y escritura, lo que hace que las operaciones de carga y almacenamiento se ejecutan puede parecer fuera de orden.

Java desde el código fuente final en una secuencia de instrucciones que realmente ejecutados, se someterá a los siguientes tres reordenación respectivamente:

La comprensión en profundidad del modelo de memoria de Java (a) - básico

1 por encima de la clasificación de compilación-estima, 2, y 3 se reordenamiento procesador. El reordenamiento podría resultar en un multiproceso problemas de visibilidad de memoria de programa. Para el compilador para compilar la atención de JMM reglas de ordenación prohíben un determinado tipo de compilador tiene un alto concepto de la especie (no todos los compiladores han desalentado el tipo prohibido). Para reordenar procesador, reglas de reordenación JMM procesador afirman compilador de Java cuando se genera una secuencia de instrucciones, un tipo particular de inserto de barrera de memoria (barreras de memoria, Intel llamado valla memoria) la instrucción para desactivar un tipo particular de instrucciones barrera de memoria por reordenar procesador (no todos los procesadores deben prohibir reordenamiento).

JMM pertenecen a modelo de memoria a nivel de lenguaje, se asegura en diferentes compiladores y diferentes plataformas de procesador, desalentado por ordenar y reordenar compilador de procesador de prohibir ciertos tipos de memoria proporcionan garantía de visibilidad constante para los programadores.

El procesador y el reordenamiento de comandos barrera de memoria

Los procesadores modernos usan los datos escritos en la memoria buffer de escritura para guardar temporalmente. tubería de instrucción buffer de escritura puede garantizar un funcionamiento continuo, es posible evitar que el procesador se detuvo a la espera de los datos de escritura demorada a la memoria generada. Mientras tanto, en lotes búferes de escritura modo de actualización, y combinar múltiples buffer de escritura de escritura a la misma dirección de memoria, se puede reducir la ocupación del bus de memoria. Aunque la escritura búfer tiene tantos beneficios, pero el buffer de escritura en cada procesador, el procesador sólo donde es visible. Esta ejecución generará naturaleza secuencial de las operaciones de memoria un impacto significativo: la memoria del procesador de lectura / escritura para la ejecución de la operación, no necesariamente la memoria real de lectura / escritura de operaciones en el mismo orden! Como ejemplo, consideremos el siguiente ejemplo:

Un procesador procesador B
a = 1; // A1

x = b; // A2
b = 2; // B1

y = a; // B2
Estado inicial: a = b = 0

, el procesador permite que los resultados de la ejecución obtuvieron: x = y = 0

Supone que el procesador A y el procesador B orden del programa de accesos a memoria a cabo en paralelo, es posible obtener un final X = Y = 0 resultados. razón específica, como se muestra a continuación:

                        La comprensión en profundidad del modelo de memoria de Java (a) - básico

Aquí Procesador Procesador A y B pueden ser escritos de manera simultánea a su buffer de escritura compartida variable (A1, B1), y luego leen otra variable compartida (A2, B2) de la memoria, y sólo entonces escribir la última memoria intermedia en su propio actualizar los datos sucios guardados en la memoria (A3, B3). Cuando se realiza en este momento, el programa puede obtener el resultado x = y = 0.

Del orden de la memoria real de operaciones de punto de vista, hasta que el procesador realiza un A3 refrescar su buffer de escritura, escribe A1 realmente implementada. Aunque las operaciones de memoria realiza el procesador secuencial como: A1-> A2, pero la secuencia real de las operaciones de memoria es: A2-> A1. En este momento, una operación de procesador Una memoria secuencial es un reordenamiento (donde el procesador A y el procesador B es el mismo, no entrar aquí).

La clave aquí es que, debido al buffer de escritura es visible sólo a su propio procesador, que dará lugar a un procesador secuencial para llevar a cabo las operaciones de memoria pueden ser incompatibles con la ejecución real del orden de las operaciones de memoria. Debido a que los procesadores modernos usarán el buffer de escritura, por lo que los procesadores modernos permitirán escritura - lectura de reordenamiento hacer gimnasia.

He aquí una lista de los procesadores comunes permiten reordenar tipos:

  Carga-carga Carga-tienda tienda tienda Tienda-Load dependencias de datos
SPARC-TSO norte norte norte Y norte
x86 norte norte norte Y norte
IA64 Y Y Y Y norte
PowerPC Y Y Y Y norte

La tabla de células "N" indica que el procesador no permite dos operación de reordenamiento, "Y" indica el reordenamiento permisible.

Podemos ver en la tabla: un procesador común permite tienda-Load reordenamiento; se permiten las operaciones del procesador común que depender de la presencia de datos no reordenamiento. SPARC-TSO y el procesador x86 tiene un modelo de memoria relativamente fuerte, que sólo permiten escritura - lectura no reordenamiento (ya que ambos utilizan el buffer de escritura).

※ Nota 1: medios de accionamiento SPARC-TSO TSO (Total tienda orden) modelo de memoria, las características del procesador SPARC.

※ Nota 2: La tabla anterior incluye x64 x86 y AMD64.

※ Nota 3: A medida que el procesador ARM modelo de memoria y modelo de memoria es muy similar al procesador PowerPC, nos ignoramos.

※ Nota 4: El texto explicará específicamente las dependencias de datos.

Con el fin de garantizar la visibilidad de la memoria, compilador de Java genera secuencia de instrucciones en una posición apropiada de la instrucción de barrera de memoria insertada para desactivar un tipo particular de reordenamiento procesador. La instrucción barrera de memoria JMM divide en las siguientes cuatro categorías:

tipo de barrera INSTRUCCIONES explicación
Barreras LoadLoad load1; LoadLoad; instalada2 Load1 asegurar que los datos se carga, y antes de toda la instrucción de carga posterior CARGAR2 carga.
Barreras StoreStore store1; StoreStore; store2 Store1 asegurar que los datos sean visibles para otros procesadores de memoria (actualización), almacenados previamente en store2 y toda instrucción de almacenamiento posterior.
Barreras LoadStore load1; LoadStore; store2 Load1 garantizar que los datos se carga, y antes de store2 toda instrucción de almacenamiento posterior a la memoria de refresco.
Barreras StoreLoad store1; Large carga; instalada2 Store1 asegurar que los datos se hace visible (referirse a la memoria de refresco), en CARGAR2 y toda la instrucción de carga posterior con otros procesadores antes de cargarlo. Después de todas las instrucciones de acceso a la memoria (instrucciones de carga y almacenamiento) antes de la barrera Barreras StoreLoad completarán antes de la ejecución de las instrucciones de acceso a memoria después de la barrera.

Barreras StoreLoad es un "versátiles" barreras, sino que también tiene el efecto de otros tres de barrera. soporte multi-procesador moderno La mayoría de la barrera (otros tipos de barreras no son necesariamente compatibles con todos los procesadores). Aplicación de la sobrecarga de barrera será muy caro, debido a que el procesador actual típicamente quiere escribir todos los datos en la memoria intermedia a la memoria de refresco (tampón totalmente al ras).

ocurre antes

JDK5 desde el principio, java utilizando el nuevo modelo de memoria JSR -133 (en el presente documento, a menos que se indique lo contrario, son JSR- 133 para el modelo de memoria). JSR-133 ocurre antes concepto propuesto por este concepto para ilustrar el funcionamiento de la visibilidad de la memoria entre. Si el resultado de la operación llevada a cabo requiere visible, que ocurre antes debe existir relación entre las dos operaciones para otra operación. Dos operaciones contempladas en el presente documento puede ser en cualquiera de un hilo, puede ser diferente entre las roscas. sucede-antes que las reglas están estrechamente relacionados con el programador de la siguiente manera:

  • reglas de secuencia del programa: cada operación de un hilo, sucede- antes de cualquier operación posterior a la rosca.
  • regla de bloqueo del monitor: un monitor para desbloquear la cerradura, ocurre- antes de esa fecha para bloquear el bloqueo del monitor.
  • normas volátiles variables: crea un campo volátil, sucede- antes de leer esta región volátil en cualquier seguimiento.
  • Transitiva: si A ocurre- antes de B, y B ocurre- antes de C, entonces A sucede- antes de C.

Tenga en cuenta que con un pasa-antes de la relación entre las dos operaciones, no quiere decir que un pre-operación debe ser realizada antes de una operación después! Antes de que suceda antes sólo requiere una operación (resultado ejecutado) después de la operación de una operación anterior visible y secuenciado antes de la segunda operación (la primera es visible a y pedidas antes de la segunda). ocurre- antes de la definición es muy delicado, el texto se especifica por la que pasa antes definido.

JMM sucede antes relación con la figura siguiente:

                      La comprensión en profundidad del modelo de memoria de Java (a) - básico

Como se muestra anteriormente, una regla sucede-antes de la compilación general corresponden a la pluralidad de procesadores y desanimado reordenación de reglas de intercalación. Para los programadores de Java, sucede antes reglas son simples y fáciles de entender, que evita que el programador para entender la visibilidad de garantía de la memoria proporcionada por JMM distancia para aprender la aplicación concreta de las normas de reordenamiento complejas, y estas reglas.

 

Publicados 136 artículos originales · ganado elogios 6 · vistas 1492

Supongo que te gusta

Origin blog.csdn.net/weixin_42073629/article/details/104741348
Recomendado
Clasificación