Sobre la palabra clave sincronizada

1, se resumen los tres más importante uso de la palabra clave sincronizada
 
Ejemplos de método modificado , la corriente aplicada a la instancia del objeto de bloqueo, antes de entrar el código de sincronización para obtener la instancia actual de la cerradura objeto.
 
La modificación de los métodos estáticos , el papel de la corriente de bloqueo objeto de clase, antes de entrar el código de sincronización de bloqueo para obtener el objeto de la clase actual. Eso es para bloquear la clase actual, se aplica a todas las instancias de objetos de la clase, ya que los miembros estáticos no pertenecen a ninguna instancia de un objeto, los miembros de la clase (estáticos indica que se trata de una clase de recurso estático, no importa cuántos nuevos objetos, sólo se una, por lo que todos los objetos de esa clase han añadido bloqueo). Así que si un método de hilo A no estático sincronizado llama a una instancia de un objeto, y las necesidades de hilo B a llamar a este método estático sincronizado pertenece a la clase de la instancia del objeto, está permitido, la exclusión mutua no va a ocurrir, porque el acceso estático sincronizado bloqueo método está ocupada las cerraduras clase actual, el acceso a sincronizada no estático bloqueo método está ocupada por la instancia actual de la cerradura objeto.
 
Modificación del bloque de código , objeto de bloqueo designado, para bloquear un objeto dado, antes de entrar en la biblioteca de código de sincronización para obtener un bloqueo determinado del objeto. Y métodos de modificación como sincronizados, sincronizados (esto) es un bloque de bloqueo del objeto actual.
 
estático sincronizado añadió palabra clave y métodos estáticos sincronizados (clase) es el bloque de código está bloqueado a la clase Class. Aquí mencionar sobre: se añade palabra clave sincronizada con el método estático es instancia de objeto no estático para cerradura. Otra cosa a destacar es: trate de no usar sincronizada (String a) porque la JVM, la piscina constante de cadena tiene una función de amortiguación!
 
sincronizado lograr una doble comprobación de bloqueo Singleton (manera thread-safe)
 
la clase Singleton {público 
    privada estática volátil uniqueInstance el Singleton; 
    privada del Singleton () { 
    } 
    public static GetUniqueInstance del Singleton () { 
       // primero determinar si el objeto tiene demasiado ejemplo, ninguna instancia del código tenía antes de entrar en la cerradura, la pesada primer cheque 
        si (uniqueInstance nula ==) { 
            // objeto de clase de bloqueo 
            el sincronizado (Singleton.class) { 
                 // comprobar el peso de la segunda 
                IF (uniqueInstance == null) { 
                    uniqueInstance los Singleton nuevos nuevos = (); 
                } 
            } 
        } 
        volver uniqueInstance; 
    } 
}

uniqueInstance usando modificaciones de palabras clave volátiles también son necesarias, uniqueInstance = new Singleton (); Este código se ejecuta realmente se divide en tres pasos:

  1. Asignar espacio de memoria para el uniqueInstance
  2. inicialización uniqueInstance
  3. El puntero uniqueInstance a la dirección de memoria asignada
Sin embargo, debido a la reordenación de instrucciones JVM característica, el orden de ejecución puede convertirse 1-> 3-> 2. reordenamiento de instrucciones en un entorno de un solo subproceso no es el primer problema, pero en un entorno multiproceso resultará en una instancia de hilo no conseguir inicializado. Por ejemplo, un hilo T1 se realiza 1 y 3, esta vez llamada T2 GetUniqueInstance (trasera) uniqueInstance que no se encuentra vacía, el flujo vuelve uniqueInstance, pero esta vez sin embargo, no se ha inicializado uniqueInstance. El uso de la instrucción JVM volátil puede prohibir la reordenación, sino también para garantizar el funcionamiento normal en un entorno multiproceso.
 
2, el principio subyacente sincronizado
 
2.1 instrucciones Case sincronizados de sincronización bloques
 
SynchronizedDemo public class { 
    método public void () { 
        sincronizado (este) { 
            System.out.println ( "sincronizado代码块"); 
        } 
    } 
}
 
Utilice javap archivos .class para generar descompilar (ejecutar javap -c -v -l -s SynchronizedDemo.class), la información del código de bytes obtiene de la siguiente manera:
 
{ 
  SynchronizedDemo pública (); 
    Firma: () V 
    banderas: ACC_PUBLIC 
    LineNumberTable: 
      Línea 1: 0 
    Código: 
      pila = 1, locales = 1, args_size = 1 
         0: aload_0        
         1:. Invokespecial # 1 // java Método / lang / Object "<init>": () V 
         4: retorno         
      LineNumberTable: 
        línea 1: 0 
  método public void (); 
    Firma: () V 
    banderas: ACC_PUBLIC 
    LineNumberTable: 
      Línea 3: 0 
      línea 4: 4 
      línea 5: 12 
      línea 6: 22 
    Código: 
      pila = 2, locales = 3, args_size = 1
         0: aload_0        
         1: dup            
         2: astore_1       
         3: MonitorEnter   
         4: getstatic # 2 // java Campo / lang / System.out: Ljava / io / PrintStream; 
         7: ldc # 3 // cadena sincronizada 
         9: invokevirtual # 4 // Método java / io / PrintStream.println: (Ljava / lang / cadena;) V 
        12: aload_1        
        13: MonitorExit    
        14: Goto 22 
        17: astore_2       
        18: aload_1        
        19: MonitorExit    
        20: aload_2        
        21: athrow         
        22: return        
      Tabla Excepción: 
         de a tipo de destino
             4 14 17 cualquier 
            17 20 17 cualquier 
      LineNumberTable: 
        línea 3: 0 
        línea 4: 4 
        línea 5: 12 
        línea 6: 22 
      StackMapTable: number_of_entries = 2 
           frame_type = 255 / * full_frame * / 
          offset_delta = 17 
          locales = [clase SynchronizedDemo, java clase / lang / Object] 
          pila = [java clase / lang / Throwable] 
           frame_type = 250 / * chuleta * / 
          offset_delta = 4 
}

Lograr bloque de sincronización sincronizado de estados utilizando las instrucciones MonitorEnter y MonitorExit, en el que la posición de inicio de instrucciones MonitorEnter de los puntos de código de sincronización a los bloques, la instrucción MonitorExit que indica la posición final del bloque de código de sincronización. Al realizar intentos de hilo de instrucción MonitorEnter adquirir un bloqueo que se adquiere monitor (monitor objeto existe en el tema de cabecera de cada objeto Java, bloqueo sincronizado se adquiere en este recorrido, se bloquean, es por eso que cualquier objeto en Java puede ser utilizado como una cerradura razón) el titular del derecho. cuando el contador es 0 puede tener éxito, adquirirá el contador de bloqueo se establece en 1 más 1. Después de realizar la instrucción MonitorExit apropiado, el contador de bloqueo se establece en 0, lo que indica que el bloqueo se libera. Si el bloqueo no puede obtener el objeto de que el hilo actual bloqueará hasta que se libere otra cerradura hilo.

2.2 caso sincronizado de métodos de modificación
 
public class {SynchronizedDemo2 
    pública sincronizado método void () { 
        System.out.println ( "sincronizado方法"); 
    } 
}
 
Del mismo modo descompilar el código de bytes de compilación de la siguiente manera:
 
{ 
  SynchronizedDemo pública (); 
    Firma: () V 
    banderas: ACC_PUBLIC 
    LineNumberTable: 
      Línea 1: 0 
    Código: 
      pila = 1, locales = 1, args_size = 1 
         0: aload_0        
         1:. Invokespecial # 1 // java Método / lang / Object "<init>": () V 
         4: retorno         
      LineNumberTable: 
        línea 1: 0 
  pública sincronizado método void (); 
    Firma: () V 
    banderas: ACC_PUBLIC, ACC_SYNCHRONIZED 
    LineNumberTable: 
      Línea 3: 0 
      línea 4: 8 
    Código: 
      pila = 2, locales = 1, args_size = 1
         0: getstatic # 2 // java Campo / lang / System.out: Ljava / io / PrintStream; 
         3: ldc # 3 // Cadena sincronizado 
         5: invokevirtual # 4 // Método java / io / PrintStream.println: (Ljava / lang / cadena;) V 
         8: retorno         
      LineNumberTable: 
        línea 3: 0 
        línea 4: 8 
}
 
modificación sincronizada del método hace instrucciones no MonitorEnter y comandos MonitorExit, hechas en nombre del identificador realmente ACC_SYNCHRONIZED, lo que indica que el método es un método sincrónico, JVM a través de la bandera de acceso ACC_SYNCHRONIZED para identificar si un método se declara como método de sincronización para llevar a cabo correspondiente llamada sincrónica.
 
En resumen, el acceso a los recursos sincronizada es la clave para resolver la sincronización entre múltiples hilos, palabra clave sincronizada puede ser garantizada por su método o bloque de código modificado en cualquier momento, sólo un hilo de ejecución.
En versiones anteriores de Java, el bloqueo de peso pesado sincronizada pertenece, ineficiente, ya que el bloqueo del monitor (monitor) es dependiente del sistema operativo subyacente para lograr la exclusión mutua de bloqueo, las hebras Java se asignan a la parte superior de los hilos del sistema operativo nativo. . Para despertar un hilo o suspender, las necesidades del sistema operativo para ayudar a completar, la necesidad de convertir de modo de usuario al modo kernel cuando se cambia entre las discusiones que opera la implementación del sistema, la transición entre un estado requiere un tiempo relativamente largo, costo de tiempo relativamente alto, es por ello sincronizado temprana razones de baja eficiencia. Afortunadamente, después de oficial de Java 6 de Java JVM a nivel de la optimización sincronizada más grande, por lo que ahora la eficiencia de bloqueo sincronizado está optimizado bastante bien. jdk1.6 aplicación de bloqueo introdujo una serie de optimización, un aumento de la cerradura y luego a pesos pesados ​​de bloqueo de bloqueo sesgada ligera demasiado excesivo, pero después de la cerradura final en un peso pesado, el rendimiento sigue siendo relativamente baja.
 
2.3 Resumen:
 
Java proporciona una función de bloqueos a la sincronización de apoyo, JVM se identifica con base en el bloque de palabras clave sincronizada sincronizada multithreading, adquiere automáticamente el bloqueo cuando el hilo entra en un bloque sincronizado, se dará a conocer de forma automática el bloqueo cuando se sale del bloque sincronizado, un hilo para adquirir el bloqueo se bloquearán otros hilos. Cada objeto Java puede ser utilizado como un bloqueo de sincronización para lograr, palabra clave sincronizada se puede utilizar para modificar los métodos de objeto, métodos estáticos y bloques de código, cuando los métodos de objeto y estáticas para modificar objetos y cerraduras son métodos objeto de clase donde, cuando requerido objeto adicional como un bloqueo cuando la modificación del bloque de código. Cada objeto Java puede ser utilizado como una razón de bloqueo se debe a que la asociación de un objeto monitor (tubo) en la cabecera del objeto, el objeto se mantenga automáticamente hilo monitor entra en el bloque sincronizado se libera automáticamente al salir de monitor de objeto, cuando el monitor objeto otros temas serán bloqueados cuando se lleva a cabo. Por supuesto, estas funcionamiento síncrono con la ayuda JVM subyacente que lograr, pero con los métodos de palabras clave modificadas sincronizados y bloques de código en la implementación subyacente es aún existen algunas diferencias. método de modificación de la palabra clave sincronizada es la sincronización implícita, es decir, sin la necesidad de controlar la instrucción de código de bytes, la JVM puede ser distinguido de acuerdo con la bandera de acceso tabla de métodos ACC_SYNCHRONIZED si el método es un método de sincronización; la palabra clave bloques de código modificadas sincronizado es la sincronización explícita, que es para controlar la liberación del hilo y mantenga el tubo a través de las instrucciones de código de bytes MonitorEnter y MonitorExit. campo _count objeto de monitor celebrada internamente, _count igual a 0 no se lleva a cabo por el tubo, el tubo _count indica mayor que 0 se ha celebrado por cada titular se añadirá hilo _count reentrante 1, el hilo que sostiene cada _count decrementa en una salida, que está integrado en la realización del principio de la re-bloqueo. Además, hay dos colas internas _EntryList objeto de monitor y _WaitSet, correspondiente a la cola síncrona y colas de las condiciones de AQS, cuando el hilo no podrá adquirir el bloqueo en la obstrucción _EntryList, el método de espera se llama cuando el hilo se bloqueará objeto _WaitSet esperando para entrar, que se construye para alcanzar el principio de bloqueo de sincronización hilo y el estado de espera.
 
 
 
3, el contraste sincronizada y ReentrantLock
 
3.1 Las dos cerraduras son reentrantes
 
Ambos son de bloqueo de reentrada. "Bloqueo Reentrante" concepto es: que puedan obtener su propio bloqueo interno de nuevo. Por ejemplo, un hilo adquiere el bloqueo de un objeto, entonces el bloqueo de objeto no ha sido puesto en libertad, de nuevo cuando se quiere adquirir un bloqueo de este objeto todavía puede entrar, si no las cerraduras de reentrada, que causaría un punto muerto. Cada vez que el mismo hilo adquiere la cerradura, los contadores de bloqueo se incrementan en uno, por lo que tiene que esperar hasta que el contador de bloqueo cae a cero con el fin de liberar el bloqueo.
 
3.2 sincronizado depende de la JVM y ReentrantLock se basan en la API
 
sincronizada es dependiente de la implementación JVM, también hablamos de frente al equipo de máquina virtual una gran cantidad de optimización de la palabra clave sincronizada en jdk1.6, pero estas optimizaciones se realizan en el nivel de la máquina virtual, y no expuesto directamente a nosotros. ReentrantLock nivel de JDK se logra (nivel de la API es decir, necesitamos bloqueo () y métodos de desbloqueo con try / finally para completar la frase).
 
3.3 ReentrantLock que sincroniza añade algunas características avanzadas
 
En comparación sincronizada, ReentrantLock añadió algunas características avanzadas. Principalmente para los tres puntos principales: ① espera puede interrumpir; ② puede lograr un bloqueo justo; ③ puede lograr notificación selectiva (bloqueo se puede unir múltiples condiciones)
  • ReentrantLock proporciona un mecanismo capaz de interrumpir el hilo a la espera de la cerradura, este mecanismo se implementa por lock.lockInterruptibly (). Está a la espera de que las discusiones pueden optar por renunciar a la espera, cambiado otras cosas.
  • ReentrantLock puede especificar si justo o injusto bloqueo de la cerradura. Las cerraduras justas único no sincronizados. El llamado bloqueo feria es el primer hilo está esperando para adquirir el bloqueo. ReentrantLock no predeterminado justo, puede ser desarrollado por clase ReentrantLock ReentrantLock (justo booleano) si el constructor es justo.
  • palabra clave y espera sincronizada () y notificar / notifyAll () método puede ser implementado en conjunción con el mecanismo de espera / notificación, por supuesto, se puede lograr la clase de ReentrantLock, pero necesitan el método Condición interfaz newCondition () ayuda. La condición es sólo después de JDK1.5, se ha buena flexibilidad, por ejemplo, puede lograr la función de notificación múltiple es crear varias instancias Condición (es decir, los monitores de objeto) en un objeto Lock, objeto hilo puede estar registrado en condición especificada, de modo que el hilo puede ser notificación selectivamente, una mayor flexibilidad en las discusiones de programación. Cuando se utiliza una notificación método / notifyAll () notificar, un hilo se notifica se selecciona por la JVM, la clase con instancia ReentrantLock Condición puede ser implementado en conjunción con "aviso selectivo", esta característica es muy importante, y está disponible por defecto la interfaz Condición. La palabra clave sincronizada es equivalente a toda la cerradura objetos solamente una instancia Condiciones, todos los temas están registrados con ella un cuerpo. Si lo hace notifyAll método () luego informar a todos los hilos en un estado de espera, causará una gran eficiencia, mientras que el método Condición ejemplo signalAll () sólo será registrado en la estela de la instancia Condición todas las discusiones de espera.
Si desea utilizar estas características, a continuación, elija ReentrantLock es una buena opción.
 
3.4 El rendimiento no es el criterio de selección
 
Antes jdk1.6, funcionamiento sincronizado es mucho peor que ReentrantLock. expresado específicamente como: sincronizada aumenta el rendimiento de la palabra clave con el número de hilos, disminución muy grave. El ReentrantLock mantuvo un nivel relativamente estable. Creo que esto es un reflejo de, hay una sala muy grande para la optimización de palabras clave sincronizada. desarrollos tecnológicos posteriores han confirmado este punto, hemos hablado anteriormente, después que el equipo jdk1.6 JVM ha hecho mucho por la optimización de palabras clave sincronizada. Después jdk1.6, sincronizado y el rendimiento ReentrantLock está básicamente fuera plana. Así que aquellos que dicen que la Internet, ya que el rendimiento antes de elegir el artículo ReentrantLock está mal! Después jdk1.6, el rendimiento no ha seleccionado y factores ReentrantLock de la sincronizada! Y mejoras en el rendimiento de la máquina virtual en el futuro estarán más inclinados a sincronizada nativa, por lo que todavía se defiende en el caso de sincronizada para satisfacer sus necesidades, dando prioridad a la utilización de la palabra clave sincronizada para sincronizar! Sincronizada y optimizado ReentrantLock, como en muchos lugares se utilizan la operación de CAS.
 
 

Supongo que te gusta

Origin www.cnblogs.com/liujiarui/p/12594292.html
Recomendado
Clasificación