2012-08-27 4 views
8

objオブジェクトに​​ブロックの数がある場合、Javaはこれらのすべてが同じかどうかを確認しますか?彼らは他のをブロックします上記の機能f、2つのスレッドによって同時に呼び出された場合Javaロック:同期ブロックで監視ロックの等価性チェックがどのように行われますか?

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

:たとえば

?各スレッドは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", "Str");f1("B", "Str");行をコメントし、その上の行のコメントを解除場合

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

をしかし、その後、結果があります: - Strバージョンは、私は多分Javaがequals CHEを使用していることを期待していたので、働いていたので

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

​​ブロック、おそらくhashCodeの場合はckですが、2番目のテストではそうではありません。

Stringは特殊なケースですか?

答えて

18

いいえ、Javaはロックモニタ用にequalsを使用しません。

ロックはオブジェクトインスタンス自体にあります。つまり、ある意味では "=="が使用されます(実際には、これは実装方法ではありません。すべてのオブジェクトに現在のロック所有者用の特別なスロットがあります)。

文字列には特別なケースはありません。

文字列リテラルがプールされ、同じリテラルを複数回使用すると、同じインスタンスが返されます(new Xnew Stringのように異なるインスタンスを作成します)。あなたの "new" Stringsでinternを呼び出すと、おそらく同じ効果が見られます。

関連する問題