2012-08-27 13 views
8

Kiedy masz kilka bloków synchronized na obiekcie (powiedzmy) obj, to w jaki sposób Java sprawdza, czy wszystkie te obj s są takie same lub różne?Blokady Java: w jaki sposób sprawdzanie równości dla blokad monitora odbywa się w bloku synchronicznym?

Na przykład:

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

Jeżeli powyższa funkcja f nazywa się jednocześnie dwa wątki będą blokować drugiego? Zauważ, że każdy wątek otrzyma nowe wystąpienie obiektu String.

Aby to sprawdzić, napisałem poniższy kod testowy i rzeczywiście wygląda na to, że powyższy blok zadziała, ale są też inne nieoczekiwane rezultaty.

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; 
     } 
    } 

} 

Po uruchomieniu powyższego kodu woli pojawić się następujący komunikat: -

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

Jednak gdybym skomentować f1("A", "Str"); i f1("B", "Str"); linie i odkomentuj linie nad nimi, a następnie wynik jest : -

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

Ponieważ wersja Str pracował więc spodziewałem się, że być może Java używa equals che ck dla synchronized bloku lub może hashCode, ale z drugiego testu wydaje się, że tak nie jest w ogóle.

Czy String jest specjalny przypadek?

Odpowiedz

18

Nie, Java nie używa equals dla monitorów blokady.

Blokada dotyczy samej instancji obiektu. Tak więc, w pewnym sensie używa on "==", jeśli tak (ale w rzeczywistości nie jest tak, jak jest on implementowany, każdy obiekt ma specjalne gniazdo dla obecnego właściciela blokady).

Nie ma specjalnego przypadku dla ciągu znaków.

Co dzieje się z ciągami jest jednak to, że literały łańcuchowe się łączono, a jeśli masz to samo dosłowne więcej niż jeden raz, będzie to prowadzić do tej samej instancji (podczas new X tworzy różne instancje, gdyż new String). Jeśli wywołasz intern na swoich "nowych" Ciągach, prawdopodobnie zobaczysz ten sam efekt.

Powiązane problemy