Barrera de la memoria

Barrera de memoria

Cada CPU tendrá su propio caché (algunos incluso L1, L2, L3. El propósito del caché es mejorar el rendimiento y evitar que cada vez sea necesario acceder a todos). internamente. Sin embargo, las desventajas de esto también son obvias: la información no se puede intercambiar con la memoria en tiempo real y diferentes subprocesos ejecutados en diferentes CPU tienen diferentes valores de caché para la misma variable.

Modificar variables con la palabra clave volátil puede resolver los problemas anteriores, entonces, ¿cómo hace esto volátil? Esa es la barrera de la memoria. La barrera de la memoria es un concepto de la capa de hardware. Diferentes plataformas de hardware tienen diferentes métodos para implementar barreras de memoria. Al proteger estas diferencias, Java unifica las instrucciones para generar barreras de memoria por parte de JVM.

Existen dos tipos de barreras de memoria en la capa de hardware: Barrera de carga y Barrera de almacenamiento, que son barreras de lectura y barreras de escritura.

Las barreras de memoria tienen dos funciones:

Para Load Barrier, insertar Load Barrier antes de la instrucción puede invalidar los datos en el caché y forzar que los datos se vuelvan a cargar desde la memoria principal;

Para Store Barrier, insertar Store Barrier después de la instrucción puede actualizar los datos más recientes en el caché de escritura y escribirlos en la memoria principal, haciéndolos visibles para otros subprocesos.

Generalmente existen cuatro de las llamadas barreras de memoria en Java, a saber, LoadLoad, StoreStore, LoadStore y StoreLoad son en realidad una combinación de las dos anteriores, completando una serie de funciones de barrera y sincronización de datos.

Barrera LoadLoad: para declaraciones como Load1; LoadLoad; Load2, asegúrese de que los datos que leerá Load1 se lean antes de que se acceda a los datos que leerá Load2 y las operaciones de lectura posteriores.

Barrera StoreStore: para declaraciones como Store1; StoreStore; Store2, antes de ejecutar Store2 y las operaciones de escritura posteriores, se garantiza que la operación de escritura de Store1 sea visible para otros procesadores.

Barrera de LoadStore: para declaraciones como Load1; LoadStore; Store2, asegúrese de que los datos que leerá Load1 se lean por completo antes de que Store2 y las operaciones de escritura posteriores se eliminen.

Barrera StoreLoad: para declaraciones como Store1; StoreLoad; Load2, antes de ejecutar Load2 y todas las operaciones de lectura posteriores, se garantiza que la escritura en Store1 será visible para todos los procesadores. Su sobrecarga es la más grande entre las cuatro barreras. En la mayoría de las implementaciones de procesador, esta barrera es una barrera universal que tiene las funciones de las otras tres barreras de memoria.

La estrategia de barrera de memoria de Volatile es muy estricta y conservadora, muy pesimista e insegura:

<. p> Debido a la función de la barrera de la memoria, se evita reordenar las variables volátiles y otras instrucciones, y se realiza la comunicación entre subprocesos, lo que hace que los volátiles exhiban las características de bloqueo.

Para los campos finales, el compilador y la CPU seguirán dos reglas de clasificación:

En resumen, el significado de las reglas anteriores se puede entender de esta manera. Todos los campos finales de un objeto han sido escritos, solo se puede hacer referencia a ellos y leerlos más tarde. Esta es también la función de la barrera de la memoria:

Escribir el campo final: después de que el compilador termine de escribir el campo final y antes del final de la estructura, se insertará una barrera StoreStore para garantizar que la barrera final anterior La escritura no se ve afectada por otros subprocesos/Visible para la CPU y evita el reordenamiento.

Lectura del campo final: En la regla 2 anterior, el mecanismo por el cual la operación de dos pasos no se puede reordenar es que la barrera LoadLoad se inserta antes de leer el campo final.

En el procesador X86, debido a que la CPU no reordena las operaciones de escritura y escritura, se omitirá la barrera StoreStore y X86 no reordenará las operaciones que tengan dependencias lógicas, por lo que LoadLoad también se omitirá.