2012-08-27 6 views
8

Cuando tiene un par de bloques synchronized en un objeto (digamos) obj, entonces, ¿cómo comprueba Java si todos estos obj s son iguales o diferentes?Bloqueos de Java: ¿cómo se realiza la comprobación de igualdad para bloqueos de monitor en bloque sincronizado?

Por ejemplo:

public static f() { 
    synchronized ("xyz") { 
     ... 
    } 
} 

Si la función f arriba se llama simultáneamente por dos hilos van a bloquear el otro? Tenga en cuenta que cada hilo obtendrá una nueva instancia del objeto String.

Para comprobar esto escribí el siguiente código de prueba, y de hecho parece que el bloque anterior funcionará, pero luego hay otros resultados inesperados.

public class Test { 

    public static void main(String[] args){ 

     new Thread() { 
      public void run() { 
       //f1("A", new X()); 
       f1("A", "Str"); 
      } 
     }.start(); 

     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     //f1("B", new X()); 
     f1("B", "Str"); 
    } 

    public static void f1(String a, Object x) { 
     synchronized(x) { 
      System.out.println("f1: " + a); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println("f1: " + a + " DONE"); 
     } 
    } 

    private static class X { 
     public boolean equals(Object o) { 
      System.out.println("equals called"); 
      return true; 
     } 

     public int hashCode() { 
      System.out.println("hashCode called"); 
      return 0; 
     } 
    } 

} 

Si ejecuta el código anterior del obtendrá el siguiente resultado: -

f1: A 
f1: A DONE 
f1: B 
f1: B DONE 

Sin embargo, si comentar los f1("A", "Str"); y f1("B", "Str"); líneas y elimine las líneas por encima de ellos, entonces el resultado es : -

f1: A 
f1: B 
f1: A DONE 
f1: B DONE 

Desde la versión Str trabajó así que estaba esperando que tal vez Java utiliza equals che ck para synchronized bloque o tal vez hashCode pero a partir de la segunda prueba parece que no es el caso en absoluto.

¿Es String un caso especial?

Respuesta

18

No, Java no usa equals para monitores de bloqueo.

El bloqueo está en la propia instancia del objeto. Entonces, de alguna manera, usa "==", si quiere (pero en realidad, no es así como se implementa. Cada objeto tiene una ranura especial para el propietario del candado actual).

No hay caso especial para String.

Lo que está sucediendo con cuerdas, sin embargo, es que los literales de cadena GET agruparon, y si tiene el mismo literal más de una vez, que se traducirá en la misma instancia (mientras que new X crea diferentes instancias, al igual que new String). Si llama al intern en sus "nuevas" Cadenas, probablemente vea el mismo efecto.

Cuestiones relacionadas