2010-03-17 11 views
6

Recientemente asistí a una presentación que trata algunos patrones de diseño:sincronización interna en el mismo objeto que la sincronización externa

El siguiente código había sido mostradas:

public static Singleton getInstance() 
{ 
    if (instance == null) 
    { 
    synchronized(Singleton.class) {  //1 
     Singleton inst = instance;   //2 
     if (inst == null) 
     { 
     synchronized(Singleton.class) { //3 
      inst = new Singleton();  //4 
     } 
     instance = inst;     //5 
     } 
    } 
    } 
    return instance; 
} 

tomadas de: Double-checked locking: Take two

Mi pregunta no tiene nada que ver con el patrón mencionado anteriormente, pero con los bloques sincronizados:

¿Hay algún beneficio en la doble sincronización realizada en las líneas 1 & 3 con respecto al hecho de que la operación de sincronización se realiza en el mismo objeto ?

Respuesta

11

En el antiguo Modelo de memoria Java (JMM), al salir de un bloque synchronized supuestamente se han eliminado datos locales de la memoria principal. Ingresar un bloque synchronized utilizado para causar la relectura de datos en caché. (Aquí, la memoria caché incluye registros con optimizaciones de compilador asociadas). La JMM anterior se rompió y no se implementó correctamente.

En el nuevo JMM no hace nada. El nuevo JMM se especifica para 1.5 e implementado para el JRE "Sol" 1.4. 1.5 completó su período de vida de fin de servicio hace algún tiempo, por lo que no debería tener que preocuparse por el viejo JMM (bueno, tal vez Java ME hará algo impredecible).

+1

bien ... ¿podría elaborar por favor? Todavía no puedo entender la utilidad de lo anterior. – Yaneeve

+0

La sincronización AFAIK todavía realiza algunos enjuagues. (Consulte http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization) –

+0

Oh, me acabo de dar cuenta de que estaba hablando de EXITING. Perdió que –

2

No soy experto en modelos de memoria, pero creo que uno debe considerar que un "sincronizado" no solo indica la necesidad de obtener un bloqueo, sino también las reglas sobre la posible optimización del código y la limpieza y actualización de cachés.

Encontrará los detalles en el Java Memory Model

+0

El nuevo Java Memory Model no se ocupa de la limpieza de cachés. Usa relaciones * pasa * antes * que son bastante diferentes. –

+1

Hmm, pero para asegurar tal relación, tiene que producirse el enjuague de los cobros. O al menos eso pensé. ¿Puede indicarme un recurso, explicando la diferencia/relación? –

2

Sincronización de dos veces en el mismo objeto hace cumplir que todos los cambios realizados en el interior del bloque interior se vacía la memoria compartida cuando se sale del bloque de sincronización interna. Pero lo que es importante tener en cuenta es que no hay reglas que digan que los cambios realizados después de que el bloque de sincronización interna no pueda realizarse antes de que se salga de la sincronización interna.

Por ejemplo

public void doSomething() 
{ 
    synchronized(this) { // "this" locked 
    methodCall1(); 
    synchronized(this) { 
     methodCall2(); 
    } // memory flushed 
    methodCall3(); 
    } // "this" unlocked and memory flushed 
} 

puede ser compilado para ejecutarse en este orden

public void doSomething() 
{ 
    synchronized(this) { // "this" locked 
    methodCall1(); 
    synchronized(this) { 
     methodCall2(); 
     methodCall3(); 
    } // memory flushed 
    } // "this" unlocked and memory flushed 
} 

Para una explicación más detallada echa un vistazo a Double Check Locking en el Una solución que no funciona sección sobre un tercio del camino hacia abajo.

Cuestiones relacionadas