Entrevistador, no cuelgues el teléfono, Sincronizado, todavía puedo hablar durante media hora.

Entrevistador, no cuelgues el teléfono, Sincronizado, todavía puedo hablar durante media hora.

La palabra clave sincronizada se usa a menudo para la sincronización de subprocesos. El hilo que ejecuta el bloque de código sincronizado modificado por Synchronized primero obtendrá el "bloqueo de objeto". Si otro hilo intenta ejecutar el bloque de código sincronizado, se bloqueará hasta que el hilo termine de ejecutar el código de sincronización y libere el "bloqueo de objeto". El concepto anterior ciertamente no es desconocido, pero cuál es el bloqueo de objeto específico, tal vez no esté muy claro, este artículo comienza a partir de sus principios subyacentes e interpreta la palabra clave sincronizada en detalle

Concepto de palabra clave sincronizada

Sincronizado es una palabra clave en Java, es usar el mecanismo de bloqueo para lograr la sincronización, el mecanismo de bloqueo tiene las siguientes dos características

  • Exclusión mutua (también llamada atomicidad) : solo un hilo puede adquirir un bloqueo de objeto a la vez

  • Visibilidad : después de que el subproceso adquiere el bloqueo del objeto, borrará las variables compartidas utilizadas por los bloques de código sincronizado en la memoria de trabajo del subproceso

    Antes de que el objeto libere el bloqueo, actualizará la modificación de la variable compartida en la memoria de trabajo del hilo de nuevo a la memoria principal

Bloqueo de objeto y bloqueo de clase

En Java, cada objeto tendrá un monitorobjeto, el objeto monitor se dice a menudo, se bloquea o se llama objeto

Monitor de bloqueo . Los bloqueos de clase (similar al uso de Sincronizado (Object.class)) se implementan realmente a través de bloqueos de objetos. Si está familiarizado con el mecanismo de carga de clases, debe saber que cuando se carga una clase, se agregará un objeto de Clase al montón. El objeto de monitor de este objeto de clase es el bloqueo de clase, que muestra que solo hay un bloqueo de clase para cada clase

Encabezado de objeto

El diseño de los objetos Java almacenados en la memoria se puede dividir en tres áreas: encabezado de objeto, datos de instancia y relleno de alineación.
El encabezado del objeto se divide en dos partes: la primera parte almacena los datos de tiempo de ejecución del objeto en sí, también conocido como Mark Word. Las máquinas virtuales de 32 bits ocupan 32 bits y las máquinas virtuales de 64 bits ocupan 64 bits. Como se muestra en la figura, bajo diferentes estados de bloqueo, la estructura de Mark Word. El puntero de la clase de almacenamiento de la segunda parte

Principio de bloqueo de objeto (monitor)

En la máquina virtual Java, ObjectMonitor implementa el monitor, la estructura de datos principal es la siguiente

 1 ObjectMonitor() {
 2     _header       = NULL;//markOop对象头
 3     _count        = 0;
 4     _waiters      = 0,//等待线程数
 5     _recursions   = 0; //重入次数
 6     _object       = NULL;
 7     _owner        = NULL;//指向获得ObjectMonitor对象的线程
 8     _WaitSet      = NULL;//处于wait状态的线程,会被加入到wait set;
 9     _WaitSetLock  = 0 ;
10     _Responsible  = NULL ;
11     _succ         = NULL ;
12     _cxq          = NULL ;
13     FreeNext      = NULL ;
14     _EntryList    = NULL ;//处于等待锁block状态的线程,会被加入到entry set;
15     _SpinFreq     = 0 ;
16     _SpinClock    = 0 ;
17     OwnerIsThread = 0 ;// _owner is (Thread *) vs SP/BasicLock
18     _previous_owner_tid = 0;// 监视器前一个拥有者线程的ID
19   }

ObjectMonitor tiene principalmente varias variables miembro que necesitan atención.

  • _owner: apunta al hilo que obtuvo el objeto ObjectMonitor
  • _EntryList: los subprocesos en el estado de espera de bloqueo se agregarán al conjunto de entradas
  • _WiatSet: el subproceso en el estado de espera se agregará al conjunto de espera (llame al método de espera del objeto de sincronización)

Múltiples subprocesos tienen acceso al mismo tiempo un cierto código de sincronización, entrará en la primera _EntryListserie fueron bloqueados a la espera de, cuando el objeto hilo es conseguir monitorde nuevo en la región propietario, y para monitorlos _ownerpuntos variables al hilo, mientras que monitorel contador de countauto más uno, si el subproceso de llamada el objeto de sincronización wait()métodos actualmente en cartera se libera monitor, _ownerla variable se pone a cero null, countya que una reducción, mientras que el hilo entra en _WaitSetla espera de despertador, el hilo ha terminado el bloque de sincronización, también _Ownery countrestablecer variables.

Proceso de desbloqueo de bloqueo de bloque de código

public class SyncCodeBlock{
    public int i;
    public void syncTask(){
        synchronized(this) {
            i++;
        }
    }
}

Después de la descompilación, obtenga el código de bytes del código anterior

public void syncTask();
    Code:
       0: aload_0
       1: dup
       2: astore_1
       3: monitorenter
       4: aload_0
       5: dup
       6: getfield      #2                  // Field i:I
       9: iconst_1
      10: iadd
      11: putfield      #2                  // Field i:I
      14: aload_1
      15: monitorexit
      16: goto          24
      19: astore_2
      20: aload_1
      21: monitorexit
      22: aload_2
      23: athrow
      24: return

Como se puede ver en el código de bytes, se utiliza la capa inferior de Sincronizado monitorentery las monitorexitinstrucciones implementan la sincronización de subprocesos.

  • Cuando monitorenterse ejecuta la instrucción, el subproceso intentará adquirir el bloqueo del objeto de sincronización (es decir, el objeto del monitor) .Si la variable de recuento del monitor (registrando el número de veces que ingresa el subproceso) es 0, establezca el recuento en 1 y _propietario del subproceso actual ''. Éxito. Si el hilo ya posee el bloqueo del objeto, puede volver a ingresarlo. El valor de la calculadora del contador también aumentará en uno al volver a ingresar

  • Al señalar la monitorexitinstrucción, el ejecutor disminuye el contador de conteo en uno. Cuando el contador es 0, otros hilos tendrán la oportunidad de retener

    Vale la pena señalar que el compilador se asegurará de que no importa cómo se complete el método, cada monitorenterinstrucción invocada en el método ejecutará la monitorexitinstrucción correspondiente , ya sea que el método finalice de manera normal o anormal.

    Si el método se completa anormalmente, el compilador generará automáticamente un controlador de excepciones. El propósito del controlador de excepciones es ejecutar la monitorexitinstrucción. También se puede ver en el código de bytes que hay una monitorexitinstrucción adicional . Es el monitor de liberación que se ejecuta cuando finaliza la excepción. Instrucción.

Método de bloqueo del cuerpo y proceso de desbloqueo

public class Main{
    public int i;
    public synchronized void syncTask(){
        i++;
    }
}

Después de descompilar el código anterior, obtienes el siguiente código de bytes

 public synchronized void syncTask();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=3, locals=1, args_size=1
         0: aload_0
         1: dup
         2: getfield      #2                  // Field i:I
         5: iconst_1
         6: iadd
         7: putfield      #2                  // Field i:I
        10: return

La sincronización del cuerpo del método es implícita, es decir, no se requieren instrucciones de código de bytes para controlar. La JVM puede ACC_SYNCHRONIZEDdistinguir si un método está sincronizado desde el indicador de acceso en la estructura de la tabla de métodos (estructura method_info) en el grupo constante de métodos .

Al llamar a un método, verifique ACC_SYNCHRONIZEDsi el método está configurado. Si está configurado, el hilo necesita sostener primero el monitor del objeto, luego ejecutar el método y finalmente liberar el monitor cuando el método se haya completado.

Si se lanza una excepción durante la ejecución de un método síncrono, y la excepción no se puede manejar dentro del método, el monitor en poder del método síncrono se liberará automáticamente cuando la excepción se arroje fuera del método síncrono.

195 artículos originales publicados · Me gusta 437 · Visitas 150,000+

Supongo que te gusta

Origin blog.csdn.net/zycxnanwang/article/details/105548817
Recomendado
Clasificación