2010-11-15 24 views
7

Ésta es mi clase de Java 1.6:¿Qué significa "sincronización inconsistente"?

public class Foo { 
    private ArrayList<String> names; 
    public void scan() { 
    if (names == null) { 
     synchronized (this) { 
     this.names = new ArrayList<String>(); 
     // fill the array with data 
     } 
    } 
    } 
} 

Findbugs dice:

Inconsistent synchronization of com.XXX.Foo.names; locked 40% of time 

¿Qué significa y qué estoy haciendo mal? Estoy tratando de evitar problemas cuando dos o más clientes llaman al Foo.scan() al mismo tiempo.

Respuesta

15

Es por culpa sólo se está sincronizando cuando se establece la variable names y no cuando lo lea. Así que entre la lectura y la escritura podría ejecutarse otro subproceso y usted crearía dos ArrayLists y los llenaría con datos, el primero creado obtendría GC.

Es necesario poner el bloque sincronizado en torno a la lectura y la escritura o añadir el modificador sincronizado con el método.

public class Foo { 
    private ArrayList<String> names; 
    public void scan() { 
     synchronized (this) 
     if (names == null) { 
      this.names = new ArrayList<String>(); 
      // fill the array with data 
     } 
     } 
    } 
    } 
+1

Si usted planea usar este lenguaje, la variable nombres están marcados como volátil. –

+0

También debe verificar si 'names' es nulo antes de ingresar al bloque sychrnoize. Esto evita el bloqueo cuando no es necesario. – Jeremy

+0

@Phil M ¿por qué los nombres se deben marcar como volátiles? Pensé que sincronizado proporciona la misma visibilidad que volátil. Entonces no agregará nada siempre y cuando todo acceso a los nombres use el mismo candado. – brain

6

La primera vez que se hace referencia en el interior namesscan está fuera de synchronized bloque.
por ejemplo, si scan se llama dos veces a partir de dos hilos diferentes y names es nulo, puede ir así

  1. if (names == null) desde el primer hilo es procesado (a true).
  2. if (names == null) desde el segundo hilo se procesa (a true).
  3. Primer hilo entra en el bloque synchronized, asigna names y sale del bloque synchronized.
  4. El segundo hilo entra en el bloque synchronized, asigna names y sale del bloque synchronized.

Ahora, names se inicializa dos veces. Y este es solo un escenario posible en el que se obtienen resultados inesperados.

+0

'bloqueado 40% de tiempo' ¿qué significa advertencia –

+0

@ org.life.java No tengo idea, quizás este no es todo el código. –

Cuestiones relacionadas