Pregunta

Vi algunos ejemplos en java donde se realiza la sincronización en un bloque de código para cambiar alguna variable, mientras que la variable fue declarado volátiles originalmente ..Vi que en un ejemplo de la clase singleton donde se declaró que la única instancia tan volátil y sincronizado el bloque que inicializa la instancia ...Mi pregunta es ¿por qué declaramos volátiles mientras nos sincronización en él, ¿por qué tenemos que hacer ambas cosas??no es uno de ellos es suficiente para el otro ??

public class someClass {
volatile static uniqueInstance = null;

public static someClass getInstance() {
        if(uniqueInstance == null) {
            synchronized(someClass.class) {
                if(uniqueInstance == null) {
                    uniqueInstance = new someClass();
                }
            }
        }
        return uniqueInstance;
    }

gracias de antemano.

¿Fue útil?

Solución

La sincronización por sí misma sería suficiente en este caso si el primer cheque estuviera dentro del bloque sincronizado (pero no es y un hilo no puede ver los cambios realizados por otra si la variable no era volátil).Solo volátil no sería suficiente porque necesitas realizar más de una operación atómicamente.¡Pero cuidado!Lo que tienes aquí es el llamado Bloqueo de doble comprobación: un idioma común, que, lamentablemente, no funciona de manera confiable .Creo que esto ha cambiado desde Java 1.6, pero aún así, este tipo de código puede ser arriesgado.

Editar : cuando la variable es volátil, este código funciona correctamente desde JDK 5 (no 6 como escribí anteriormente), pero no funcionará como se espera bajo JDK 1.4 o antes.

Otros consejos

Para ello se utiliza el registrado el doble de bloqueo, tenga en cuenta que el if(uniqueInstance == null) no está dentro de la sincronizado parte.

Si uniqueInstance no es volátil, podría ser "inicializado" con una parte del objeto construido, donde las partes de la misma no es visible para los demás que el hilo de ejecución en el synchronized el bloque.volátil que hace de este un todo o nada el funcionamiento en este caso.

Si usted no tiene la sincronizado bloque, usted podría terminar con 2 hilos llegar a este punto y en el mismo tiempo.

if(uniqueInstance == null) {
      uniqueInstance = new someClass(); <---- here

Y construir 2 SomeClass objetos, que derrota el propósito.

Estrictamente hablando, no es necesario volátiles , el método podría haber sido

public static someClass getInstance() {
    synchronized(FullDictionary.class) {
         if(uniqueInstance == null) {
             uniqueInstance = new someClass();
          }
         return uniqueInstance;
    }
}

Pero que incurre en la sincronización y la serialización de cada subproceso que realiza getInstance().

Esta publicación explica la ideadetrás volátil.

También se aborda en el trabajo seminal, concurrencia de Java en la práctica .

La idea principal es que la concurrencia no solo implica la protección del estado compartido, sino también la visibilidad de ese estado entre los hilos: aquí es donde viene el volátil. (Este contrato más amplio está definido por el Modelo de memoria Java .)

Puede hacer sincronización sin usar bloque sincronizado. No es necesario usar la variable volátil en él ... Volatile actualiza la una variable de la memoria principal ... y Actualización sincronizada Todas las variables compartidas que se han accedido desde la memoria principal. Para que pueda usarlo de acuerdo a su requerimiento ..

mis dos centavos aquí

frist Una explicación rápida de la intuición de este código

if(uniqueInstance == null) {
        synchronized(someClass.class) {
            if(uniqueInstance == null) {
                uniqueInstance = new someClass();
            }
        }
    }

La razón por la que verifica el únicoInstance== NULL dos veces es reducir la sobrecarga de llamar al bloque sincronizado que es relativamente más lento.El llamado bloqueo de doble comprobación.

Segundo, la razón por la que usa sincronizada es fácil de entender, realiza las dos operaciones dentro del bloque sincronizado atómico.

Por último, el modificador volátil se asegura de que todos los subprocesos ven la misma copia, por lo que la primera comprobación fuera del bloque sincronizada verá el valor de una forma única de una manera "sincronizada" con el bloque sincronizado.Sin el modificador volátil, un hilo puede asignar un valor a un últimoInstancia, pero el otro hilo puede no verlo por primera comprobación.(Aunque el segundo cheque lo verá)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top