En el procesamiento de concurrencia de hilo Java, hay mucha confusión en el uso de una palabra clave volátil. Creo que usar esta palabra clave puede hacer que todo vaya bien cuando se usa el procesamiento de concurrencias múltiples.
El lenguaje Java admite múltiples subprocesos. Para resolver el problema de la concurrencia de hilo, el bloque sincrónico y el mecanismo de palabras clave volátil se introducen dentro del lenguaje.
sincronizado
Todos están familiarizados con los bloques sincronizados, y se implementan a través de la palabra clave sincronizada. Con declaraciones sincronizadas y de bloque, solo un hilo puede usarlos al mismo tiempo al acceder a múltiples hilos.
Método o bloque de código modificado sincronizado.
volátil
Para las variables modificadas con volátiles, el hilo leerá el valor más modificado de la variable cada vez que usa la variable. Volátil se usa fácilmente y se usa para operaciones atómicas.
Veamos un ejemplo a continuación. Implementamos un contador. Cada vez que se inicia el hilo, se llamará al método contador Inc para agregar uno al mostrador.
Entorno de ejecución - Versión JDK: JDK1.6.0_31, memoria: 3G CPU: x86 2.4g
Public Class Counter {public static int count = 0; public static void inc () {// El retraso aquí es 1 milisegundo, haciendo que el resultado intente obvio {Thread.sleep (1);} Catch (InterruptedException e) {} Count ++;} public static void main (string [] args) {// comienza 1000 hilos en el mismo tiempo, realiza i ++ cálculos e cálculos y vea el resultado (inti (] inti (] inti (inti (vea inti). i <1000;Resultado de ejecución: contador.count = 995
El resultado de la operación real puede ser diferente cada vez. El resultado de la máquina es: Running Result: Count.Count = 995. Se puede ver que en un entorno múltiple, el recuento no espera que el resultado sea 1000.
Muchas personas piensan que este es un problema de concurrencia multiproceso. Solo necesita agregar volátil antes del recuento de variables para evitar este problema. Luego estamos modificando el código para ver si el resultado cumple con nuestras expectativas.
public class Counter {public volatile static int count = 0;public static void inc() {//The delay here is 1 millisecond, making the result obvious try {Thread.sleep(1);} catch (InterruptedException e) {}count++;}public static void main(String[] args) {//Start 1000 threads at the same time, perform i++ calculations, and see the actual result for (int i = 0;Resultado en ejecución: contador.count = 992
El resultado de la operación aún no es tan 1000 como esperábamos. Analicemos las razones a continuación
En el artículo de Java Garbage Collection, se describe la asignación de la memoria en el momento de JVM. Una de las áreas de memoria es la pila de máquina virtual JVM, y cada hilo tiene una pila de subprocesos cuando se ejecuta.
La pila de subprocesos guarda la información del valor variable durante el tiempo de ejecución del hilo. Cuando un subproceso accede al valor de un cierto objeto, primero encuentre el valor de la variable correspondiente a la memoria del montón a través de la referencia del objeto, y luego coloque la memoria del montón
El valor específico de la variable se carga en la memoria local del hilo y se crea una copia de la variable. Después de eso, el subproceso ya no tiene ninguna relación con el valor variable del objeto en la memoria del montón, sino que modifique directamente el valor de la variable de copia.
En un cierto momento después de la modificación (antes de que salga el subproceso), el valor de la copia de la variable de subproceso se vuelve a escribir automáticamente a la variable del objeto en el montón. De esta manera, el valor del objeto en el montón cambiará. La siguiente imagen
Leer y cargar variables de copia desde la memoria principal a la memoria de trabajo actual
Use y asigne el código de ejecución para cambiar el valor de la variable compartida
Almacene y escriba Actualizar contenido relacionado con la memoria principal con datos de memoria de trabajo
donde el uso y la asignación puede aparecer varias veces
Sin embargo, estas operaciones no son atómicas, es decir, después de la carga de lectura, si la variable de recuento de memoria principal se modifica, el valor en la memoria de trabajo de subproceso no causará cambios correspondientes desde que se ha cargado, por lo que el resultado calculado será diferente de la esperada.
Para las variables modificadas por Volatile, la máquina virtual JVM solo garantiza que el valor cargado de la memoria principal a la memoria de trabajo de subprocesos sea la última
Por ejemplo, si el hilo 1 y el hilo 2 realizan operaciones de lectura y carga, y encuentran que el valor del recuento en la memoria principal es 5, entonces el último valor se cargará
Después de que el recuento de montón se modifique en el subproceso 1, se escribirá en la memoria principal, y la variable de recuento en la memoria principal se convertirá en 6.
Dado que Thread 2 ya ha realizado la operación de lectura y carga, el valor variable del recuento de memoria principal también se actualizará a 6 después de la operación.
Esto hace que ocurra la concurrencia después de que dos hilos se modifican con la palabra clave volátil en el tiempo.
Lo anterior es el significado de la palabra clave volátil en Java presentada por el editor. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje y el editor le responderá a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!