Dos métodos para resolver el problema de visibilidad de la memoria en Java multiproceso: algoritmo sincronizado, volátil y CAS


Prefacio

Primero, entendemos brevemente el modelo de memoria de Java, y luego damos lugar a problemas de visibilidad de la memoria basados ​​en un fragmento de código.

  • Modelo de memoria de Java El modelo de memoria de
    Java estipula que todas las variables se almacenan en la memoria principal. Cada subproceso tiene su propia memoria de trabajo. La memoria de trabajo del subproceso almacena las variables utilizadas por el subproceso (estas variables son de la memoria principal Copiado de) . Todas las operaciones (lectura, asignación) de variables por subprocesos deben realizarse en la memoria de trabajo.Los diferentes subprocesos no pueden acceder directamente a las variables en la memoria de trabajo del otro, y la transferencia de valores de variables entre subprocesos debe completarse a través de la memoria principal .

  • Ejemplo de código

public class 内存可见性问题 {
    
    
    public static void main(String[] args) {
    
    
        MyRunable0 myRunable0 = new MyRunable0();
        Thread th = new Thread(myRunable0);
        th.start();
        while (true){
    
    
            //程序没有进入,线程在其工作内存中将共享变量值修改为true,但是没能及时刷新到主存中
            if(myRunable0.isFlag()){
    
    
                System.out.println("进来了");
                break;
            }
        }

    }
}
class MyRunable0 implements Runnable{
    
    
    boolean flag=false;

    public boolean isFlag() {
    
    
        return flag;
    }

    public void setFlag(boolean flag) {
    
    
        this.flag = flag;
    }

    @Override
    public void run() {
    
    
        flag=true;
        System.out.println("线程将flag改成"+flag);

    }
}
  • resultado de la operación
    Inserte la descripción de la imagen aquí
  • Visibilidad
    La modificación de un valor de variable compartida por un hilo puede ser visto por otros hilos en el tiempo.
  • Atomicidad
    Atomicidad significa que la operación es indivisible. Ya sea de múltiples núcleos o de un solo núcleo, una cantidad atómica, solo un hilo puede operar en él a la vez.
  • Logra condiciones visibles
  1. El valor de la variable compartida modificado por el hilo se puede actualizar de la memoria de trabajo a la memoria principal a tiempo
  2. Otros subprocesos pueden actualizar el último valor de las variables compartidas de la memoria principal a su propia memoria de trabajo a tiempo
  • Implementación de visibilidad admitida en el nivel de lenguaje Java
  1. sincronizado
  2. volátil

Uno, sincronizado para lograr visibilidad

1.se puede lograr sincronizado

  • Atomicidad (sincronización)
  • Visibilidad

2. Dos regulaciones de JVM sobre sincronizadas

  • Antes de que se desbloquee el subproceso, el último valor de la variable compartida debe vaciarse en la memoria principal.
  • Cuando el hilo está bloqueado, el valor de la variable compartida en la memoria de trabajo se borrará, por lo que al usar la variable compartida, el último valor debe volver a leerse desde la memoria principal.

3. Código

        while (true){
    
    
        //使用 synchronized实现可见性,注意锁的使用
           synchronized (myRunable0){
    
    
               if (myRunable0.isFlag()) {
    
    
                   System.out.println("进来了");
                   break;
               }
           }
        }

4. Desventajas de sincronizado

  • No se puede controlar la longitud real del bloque
  • El bloqueo no se puede interrumpir
  • Baja eficiencia

Dos, volátil logra visibilidad

1. Se puede lograr lo volátil

  • Problemas de visibilidad
  • Sin garantía de atomicidad

2. Principio de implementación

Se logra agregando barreras de memoria y prohibiendo el reordenamiento de la optimización.

  • Al realizar una operación de escritura en una variable volátil, se agregará una instrucción de barrera de tienda después de la operación de escritura.
  • Al realizar una operación de lectura en una variable volátil, se agrega una instrucción de barrera de carga antes de la operación de lectura

En términos sencillos, cada vez que un hilo accede a una variable volátil, el valor de la variable se ve obligado a volver a leer desde la memoria principal. Cuando la variable cambia, obligará al hilo a actualizar el último valor al principal. memoria. De esta manera, en cualquier momento, diferentes hilos siempre pueden ver el último valor de la variable.

3. Código

		//在共享变量前添加volatile关键字
 volatile boolean flag=false;

4. Escenarios aplicables de volátiles

  • La operación de escritura de la variable no depende de su valor actual
  • La variable no se incluye en una invariante con otras variables.

3. Algoritmo CAS (Compare-And-Swep)

1. Información general

  • CAS, Compare and Swap compare e intercambie.Hay un total de tres operandos, un valor de memoria v, un valor antiguo de memoria local de subproceso a (el valor antes de la operación deseada) y un valor nuevo b. Durante la operación, compare el valor antiguo a y el valor de memoria v para ver los cambios Si no hay cambio, el valor de memoria v se puede actualizar al nuevo valor b. Si hay un cambio, no se cambiará.

2. Código

public class CAS算法 {
    
    
    public static void main(String[] args) {
    
    
        Mrunable mrunable = new Mrunable();
        for (int i = 0; i < 10; i++) {
    
    
            new Thread(mrunable).start();
        }

    }
}
class Mrunable implements Runnable{
    
    
    //Java提供好的原子变量
    AtomicInteger i=new AtomicInteger(1);
    
    public AtomicInteger getI() {
    
    
        return i;
    }

    @Override
    public void run() {
    
    
        while (true){
    
    
            try {
    
    
                Thread.sleep(50);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            //使用原子变量调用相应的方法完成需求
            System.out.println(i.getAndIncrement());
        }


    }
}

para resumir

Comparación sincronizada y volátil

  • Volátil no requiere bloqueos, es más liviano que sincronizado y no bloquea los hilos
  • Desde la perspectiva de la visibilidad de la memoria, las operaciones de lectura volátiles equivalen al bloqueo y las operaciones de escritura volátiles equivalen al desbloqueo.
  • Sincronizado puede garantizar tanto la visibilidad como la atomicidad, mientras que lo volátil solo puede garantizar la visibilidad y no puede garantizar la atomicidad.

Supongo que te gusta

Origin blog.csdn.net/m0_46988935/article/details/112937371
Recomendado
Clasificación