2010-08-30 14 views
15

¿Por qué esta clase de Java no es segura?Seguridad de subprocesos en la clase Java

class TestClass { 
    private int x; 

    int get() { 
     return x; 
    } 

    void set(int x) { 
     this.x = x; 
    } 
} 

leí esa palabra clave synchronized se necesita para que sea hilo de seguridad? Después de todo, ¿las operaciones no se realizan dentro de atómica?

+1

private void int x? –

Respuesta

11

Aunque la asignación en sí es una operación atómica, debido a diferentes implementaciones de hardware y compilador, diferentes subprocesos pueden ver diferentes valores del miembro x. Es decir, una modificación por un hilo puede ser invisible para el otro hilo, debido a algún tipo de almacenamiento en caché. Esto generalmente se llama un problema de visibilidad de subprocesos .

Puede sincronizar su código correctamente sincronizándolo en un monitor (usando la palabra clave sincronizada o los bloqueos java.util.concurrent), o declarando que x es volátil.

+0

¿Es lo mismo en C# también? – devnull

8

Con varios procesadores, el procesador puede almacenar en caché algunos valores y es posible que no reflejen los cambios realizados por otros hilos/procesadores para los mismos objetos. En realidad, JVM puede implementarse para funcionar de esta manera incluso con un solo procesador.

La especificación del lenguaje requiere explícitamente métodos sincronizados para presentar una barrera de memoria y requieren volver a leer todas las variables de instancia de la memoria.

Como su código no está sincronizado, un hilo puede establecer el valor, pero el otro hilo devolverá el valor aún almacenado en caché por ese hilo.

Lea el capítulo 'Memory and Locks' de la Especificación del lenguaje Java.

+1

Motivo del voto a favor? –

5

Como el campo 'x' no se declara volátil, no es necesario que la JVM se asegure de que 'x' sea visible para todos los demás hilos. Es decir. si un hilo está leyendo constantemente el valor de 'x' y otro hilo lo está escribiendo, es posible que el hilo de lectura nunca "vea" el cambio de valor.

No se requiere una palabra clave sincronizada, pero funcionará, ya que creará la barrera de memoria/caché necesaria para garantizar que 'x' esté visible, pero usar la palabra clave volátil en este caso será más eficiente.

1

Cuando tiene dos métodos para modificar/acceder a una variable no volátil, nunca es seguro para subprocesos. Si quiere tener solo un método, puede probar:

synchronized int getAndSet(int x, boolean set) { 
    if (set) this.x = x; 
    return this.x; // param x is for set 
} 
Cuestiones relacionadas