2012-08-27 3 views
8

Wenn Sie ein paar synchronized Blöcke auf einem Objekt haben (sagen wir) obj dann wie überprüft Java, ob alle diese obj s gleich oder verschieden sind?Java-Sperren: Wie wird die Gleichheitsprüfung für Monitor-Sperren im synchronisierten Block durchgeführt?

Zum Beispiel:

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

Wenn die obige Funktion f gleichzeitig von zwei Threads aufgerufen wird, werden sie die andere blockieren? Beachten Sie, dass jeder Thread eine neue Instanz des Objekts String erhält.

Um dies zu überprüfen, habe ich den folgenden Testcode geschrieben, und es scheint in der Tat, dass der obige Block funktioniert, aber dann gibt es andere unerwartete Ergebnisse.

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

} 

Wenn Sie den obigen Code ausführen, um die Sie erhalten die folgende Ausgabe: -

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

Allerdings, wenn ich die f1("A", "Str"); und f1("B", "Str"); Linien Stellung zu nehmen und die Zeilen über ihnen Kommentar-, dann das Ergebnis ist : -

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

Da die Str Version gearbeitet, so dass ich es erwartet hatte vielleicht Java verwendet equals che ck für synchronized Block oder vielleicht hashCode aber aus dem zweiten Test scheint es, es ist überhaupt nicht der Fall.

Ist String ein Sonderfall?

Antwort

18

Nein, Java verwendet equals nicht für Lock-Monitore.

Die Sperre ist auf der Objektinstanz selbst. In gewisser Weise verwendet es "==", wenn Sie so wollen (aber in Wirklichkeit ist es nicht so, wie es implementiert ist. Jedes Objekt hat einen speziellen Slot für den aktuellen Besitzer der Sperre).

Es gibt keinen speziellen Fall für String.

Was mit Strings geschieht, ist jedoch, dass Stringliterale gepoolt werden, und wenn Sie die gleiche wörtliche mehr als einmal haben, wird es in der gleichen Instanz führen (während new X verschiedene Instanzen erzeugt, als würde new String). Wenn Sie auf Ihren "neuen" Strings intern aufrufen, sehen Sie wahrscheinlich den gleichen Effekt.

Verwandte Themen