2012-08-27 42 views
8

如果在對象(比如說)obj上有​​塊,那麼Java如何檢查這些obj是否相同或不同?Java鎖定:如何在同步塊中完成監視器鎖定的相等性檢查?

例如:

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

如果上述功能f同時由兩個線程它們將阻止另一種叫?注意每個線程都會得到一個新的String對象實例。

爲了檢查這個,我寫了下面的測試代碼,看起來上面的代碼塊確實可以工作,但是還有其他意想不到的結果。

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

} 

如果你運行上面的代碼,你會得到下面的輸出: -

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

但是,如果我評論了f1("A", "Str");f1("B", "Str");線並取消它們上面的線,那麼結果是: -

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

由於Str版本的工作,所以我期待,也許Java使用equals車CK爲​​塊或可能hashCode,但從第二次測試看來,情況並非如此。

String的特例嗎?

回答

18

不,Java不會將equals用於鎖定監視器。

鎖在對象實例本身上。所以,從某種意義上說,它使用「==」,如果你願意的話(但實際上,這不是它的實現方式。每個對象都有一個特殊的當前鎖擁有者的插槽)。

字符串沒有特殊情況。

什麼用繩子發生的事情,不過,是字符串字面得到彙集,如果你曾經不止一次相同的文字多了,就會導致同一個實例(而new X創建不同的情況下,正如new String)。如果您在「新」字符串上撥打intern,則可能會看到相同的效果。