Representación de uso sincronizado

¡Acostúmbrate a escribir juntos! Este es el día 11 de mi participación en el "Desafío de actualización de abril del nuevo plan diario de Nuggets", haga clic para ver los detalles del evento

Cómo usar sincronizado

Cada objeto en Java puede actuar como un candado, que se puede expresar de las siguientes tres formas:

  1. Modifica los métodos ordinarios, el bloqueo es el objeto de instancia actual;
  2. Decora el método de sincronización estática, el candado es el objeto Class de la clase actual
  3. Modificar el bloque de código, el candado es el objeto configurado en los paréntesis sincronizados;

Echemos un vistazo a estos métodos de bloqueo por ejemplo.

método sincronizado

public synchronized void addIEl método de sincronización está bloqueado. Después de usar el comando para convertir el archivo javap -c -v FileName.class en instrucciones de bytecode,

Los resultados principales son los siguientes:

public void addII(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
  stack=3, locals=3, args_size=2

.... 省略

public synchronized void addI(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC, java 
Code:
  stack=3, locals=3, args_size=2

复制代码

Puede ver que hay un indicador ACC_SYNCHRONIZED en el bloque del método de sincronización, lo que indica que este método está sincronizado. Los indicadores de métodos asincrónicos no tienen el indicador ACC_SYNCHRONIZED.

sincronización de métodos estáticos

public class InternalVariable {

    public static void addIII(String username){
        // ... 代码省略
    }
}
复制代码

Descompilar para ver los resultados principales de la compilación:

public static synchronized void addIII(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
  stack=3, locals=3, args_size=1
复制代码

Comparado con el método ordinario, el método estático tiene un ACC_STATIC más en la bandera de banderas.

Bloque de código sincronizado

public class InternalVariable {
    public void addIIII(String username) {
        synchronized (this) {
            // ... 代码
        }
    }
}
复制代码

Los resultados de la descompilación son los siguientes:

  public void addIIII(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=6, args_size=2
         0: aload_0
         1: dup
         2: astore_2
         3: monitorenter
         // ... 省略
       135: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       138: aload_2
       139: monitorexit
       140: goto          150
       143: astore        5
       145: aload_2
       146: monitorexit
       147: aload         5
       149: athrow
       150: return
复制代码

El bloque de código de sincronización tiene un monitorenter, pero dos monitorexit. Esto se debe a que la JVM generará automáticamente un controlador de excepciones para garantizar que el método pueda liberar el bloqueo normalmente cuando se produzca una excepción. El propósito es ejecutar la instrucción monitorexit.

Implementación subyacente sincronizada

La implementación subyacente de sincronizado depende de la JVM.La implementación de la sincronización en la JVM se implementa a través de las instrucciones monitor de entrada y salida del monitor de bloqueo del monitor, o implícitamente a través de la llamada al método (detección del indicador de sincronización) y la instrucción de retorno. Estos dos, el primero corresponde al bloque de código de sincronización, el último corresponde al método de sincronización, el método de sincronización estática.

Por lo tanto, el método de sincronización finalmente completa la sincronización del subproceso a través del bloqueo del monitor, lo que no viola la sincronización en la JVM a través de la entrada y salida del monitor.

Supongo que te gusta

Origin juejin.im/post/7085409584164110367
Recomendado
Clasificación