Comprensión profunda del punto de conocimiento del modelo de máquina virtual Java-memoria Java

¿Por qué concurrencia?

  1. Una razón muy importante es que la brecha entre la velocidad de cómputo de la computadora y su subsistema de almacenamiento y comunicación es demasiado grande, se dedica mucho tiempo a E / S de disco, comunicación de red o acceso a bases de datos. Y dejar que la computadora procese varias tareas al mismo tiempo es la forma más fácil de pensar y demostrar que es un medio muy efectivo de "exprimir" la potencia informática del procesador.
  2. Además de hacer un uso completo de las capacidades de los procesadores de computadora, es otro escenario de aplicación concurrente más específico que un servidor proporciona servicios a múltiples clientes simultáneamente. Para medir el rendimiento de un servicio, el número de transacciones por segundo (Transacciones por segundo, TPS) es uno de los indicadores más importantes. Representa el número total de solicitudes a las que el servidor puede responder en promedio en un segundo, y el valor de TPS y el programa La concurrencia tiene una relación muy cercana.

Eficiencia y consistencia del hardware.

El "cálculo" del procesador no puede completar la mayoría de las tareas informáticas. El procesador debe al menos interactuar con la memoria, como leer los datos de la operación y almacenar los resultados de la operación. Esta operación de E / S es difícil de eliminar ( No se puede confiar en los registros para completar todas las tareas de cálculo)

Dado que la velocidad de cómputo del dispositivo de almacenamiento de la computadora y el procesador tienen varios órdenes de diferencia de magnitud, las computadoras modernas tienen que agregar una capa de caché (caché) que lee y escribe lo más cerca posible de la velocidad de cómputo del procesador. Memoria intermedia entre: Una vez que se completa la operación, se sincroniza desde la memoria caché a la memoria, de modo que el procesador no tenga que esperar a que la lectura y escritura de la memoria sea lenta.

Coherencia de caché : para resolver el problema de coherencia de caché, cada procesador debe seguir algunos protocolos al acceder al caché y operar de acuerdo con el protocolo al leer y escribir, tales protocolos incluyen MSI, MESI, MOSI, Synapse, etc. .

Optimización de ejecución fuera de orden : para que la unidad de computación dentro del procesador esté lo más llena posible, el procesador puede optimizar la ejecución fuera de orden (Ejecución fuera de orden) del código de entrada, y el procesador se estropeará después del cálculo El resultado de la ejecución secuencial se reorganiza para garantizar que el resultado sea coherente con el resultado de la ejecución secuencial, pero no garantiza que el orden de cálculo de cada instrucción en el programa sea coherente con el orden en el código de entrada.

modelo de memoria java

Memoria principal y memoria de trabajo.

El modelo de memoria Java estipula que todas las variables se almacenan en la memoria principal y cada subproceso tiene su propia memoria de trabajo. La memoria de trabajo contiene una copia de la copia de la memoria principal de las variables utilizadas por el subproceso y todas las operaciones en las variables (leer , Asignación, etc.) deben realizarse en la memoria de trabajo y no pueden leer y escribir directamente variables en la memoria principal. Diferentes subprocesos no pueden acceder directamente a las variables en la memoria de trabajo de la otra parte, y la transferencia de valores de variables entre subprocesos debe completarse a través de la memoria principal.

En un nivel inferior, la memoria principal corresponde directamente a la memoria del hardware físico. Para obtener una mejor velocidad de funcionamiento, la máquina virtual (incluso las medidas de optimización del sistema de hardware en sí) puede permitir que la memoria de trabajo se almacene preferentemente en el registro y la memoria caché Medio, porque el acceso principal para leer y escribir es la memoria de trabajo cuando se ejecuta el programa.

Operación entre memorias

Con respecto al protocolo de interacción específico entre la memoria principal y la memoria de trabajo, las siguientes 8 operaciones se definen en el modelo de memoria Java para completar. La implementación de la máquina virtual debe garantizar que cada operación mencionada a continuación sea atómica e indivisible.

  • lock (lock): actúa en la memoria principal e identifica una variable como un estado exclusivo de subproceso
  • desbloquear
  • leer (leer): transfiere el valor de una variable desde la memoria principal a la memoria de trabajo del hilo para la acción de carga posterior
  • carga: coloca el valor variable obtenido de la operación principal de la operación de lectura en la copia variable de la memoria de trabajo
  • uso: Pase el valor de una variable en la memoria de trabajo al motor de ejecución. Esta operación se ejecutará siempre que la máquina virtual encuentre una instrucción de código de bytes que necesite usar el valor de la variable
  • asignar: Asigna el valor recibido del motor de ejecución a una variable en la memoria de trabajo
  • store: transfiere el valor de una variable en la memoria de trabajo a la memoria principal
  • escribir: Ponga el valor de la variable obtenida por la operación de almacenamiento de la memoria de trabajo en la variable de la memoria principal

Nota : El modelo de memoria Java requiere operaciones secuenciales: lectura-> carga; almacenamiento-> escritura. Sin embargo, solo se requiere una ejecución secuencial y no hay garantía de ejecución continua.

Reglas especiales para variables volátiles.

Cuando una variable se define como volátil, tendrá dos características:

Asegure la visibilidad de esta variable a todos los hilos

Aquí "visibilidad" significa que cuando un hilo modifica el valor de esta variable, el nuevo valor es inmediatamente conocido por otros hilos.

Las variables volátiles solo pueden garantizar la visibilidad. En los escenarios de operación que no cumplen con las dos reglas siguientes, todavía tenemos que garantizar la atomicidad mediante el bloqueo (utilizando la clase atómica en sincronizado o java.util.concurrent).

  • El resultado de la operación no depende del valor actual de la variable, o puede garantizar que solo un subproceso modifique el valor de la variable
  • Las variables no necesitan participar en restricciones constantes con otras variables de estado
Prohibir la optimización de reordenamiento de instrucciones

Las variables ordinarias solo aseguran que se obtengan los resultados correctos en todos los lugares que dependen del resultado de la asignación durante la ejecución del método, pero no pueden garantizar que el orden de las operaciones de asignación de variables sea el mismo que el orden de ejecución en el código del programa.

Barrera de memoria: https://www.jianshu.com/p/64240319ed60

Reglas especiales para variables largas y dobles.

Acuerdo no atómico

El modelo de memoria Java requiere que las ocho operaciones de bloqueo, desbloqueo, lectura, carga, asignación, uso, almacenamiento y escritura sean todas atómicas, pero para los tipos de datos de 64 bits (largos y dobles), uno relativamente suelto se define específicamente en el modelo Regulaciones: permita que la máquina virtual divida las operaciones de lectura y escritura de datos de 64 bits que no se modifican por volátil en dos operaciones de 32 bits, es decir, permita que la máquina virtual implemente la selección de carga, almacenamiento, lectura y Escribe la atomicidad de estas 4 operaciones.

Principio preventivo

La ocurrencia anticipada es una relación de orden parcial entre dos operaciones definidas en el modelo de memoria Java. Si la operación A ocurre antes de la operación B, significa que antes de que ocurra la operación B, el impacto de la operación A puede ser observado por la operación B. La "influencia" incluye la modificación del valor de las variables compartidas en la memoria, el envío de mensajes y los métodos de llamada.

Algunas relaciones "naturales" preexistentes bajo el modelo de memoria java
  • Regla de orden del programa : dentro de un hilo, el programa controla el orden de flujo de acuerdo con el código
  • Regla de bloqueo del monitor : se produce una operación de desbloqueo antes de la operación de bloqueo en el mismo bloqueo
  • Regla de inicio de subproceso
  • Regla de variable volátil : una operación de escritura en una variable volátil ocurre primero después de una operación de lectura en esta variable
  • Regla de terminación de hilo
  • Regla de interrupción de subprocesos (regla de interrupción de subprocesos) : la llamada al método de interrupción de subprocesos () ocurre antes de que el código del subproceso interrumpido detecte la ocurrencia de un evento de interrupción, y si el método Thread.interrupted () puede detectar una interrupción.
  • Regla de finalización de objeto (regla de finalizador) : la inicialización de un objeto (el final de la ejecución del constructor) se produce primero al comienzo de su método finalize ()
  • Transitividad : si la operación A ocurre antes de la operación B y la operación B ocurre antes de la operación C, entonces se puede concluir que la operación A ocurrió antes de la operación C

Java e hilo

Implementación de hilos
  • Usa hilos de kernel
  • Usar hilo de usuario
  • Uso mixto de hilos de usuario y procesos livianos
implementación de hilo java

Para SunJDK, su versión de Windows y Linux se implementan utilizando un modelo de subprocesos uno a uno, un subproceso java se asigna a un proceso ligero.

programación de hilos de Java

proceso Thread programación se refiere a un hilo asignado a los derechos de uso del sistema de procesador, hay dos programación principal, a saber cooperativa programación de subprocesos (Cooperativa Hilos-Scheduling) y una programación de subprocesos preventivo (de Preferencia Hilos-Programación)

Programación cooperativa de hilos

Si utiliza un sistema multiproceso de programación coordinada, el tiempo de ejecución del subproceso está controlado por el mismo subproceso. Después de que el subproceso finaliza su trabajo, debe notificar activamente al sistema para cambiar a otro subproceso.

Ventajas : simple de implementar, y debido a que el hilo cambiará el hilo después de terminar su propio trabajo, la operación de conmutación es conocida por el mismo hilo, por lo que no hay problema de sincronización de hilo

Desventajas : el tiempo de ejecución del hilo es incontrolable

Programación preventiva de hilos

Si se utiliza un sistema de subprocesos múltiples con programación preventiva, el sistema asignará tiempo de ejecución a cada subproceso, y el propio subproceso no determinará la conmutación de subprocesos.

8 artículos originales publicados · Me gusta1 · Visitas 262

Supongo que te gusta

Origin blog.csdn.net/qq_40635011/article/details/105429062
Recomendado
Clasificación