12

オブジェクトにいくつかのsynchronizedブロックがある場合 (たとえば) 、Java はこれらすべてのs が同じか異なるかobjをどのようにチェックしますか?obj

例えば:

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

上記の関数fが2つのスレッドによって同時に呼び出された場合、それらは他のスレッドをブロックしますか? 各スレッドが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

バージョンが機能していたので、 Java がブロックのチェックをStr使用するか、またはおそらく使用することを期待していましたが、2 番目のテストからはそうではないようです。equalssynchronizedhashCode

String特殊なケースですか?

4

1 に答える 1

24

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

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

String には特別なケースはありません。

ただし、文字列で何が起こっているかというと、文字列リテラルがプールされ、同じリテラルを複数回使用すると、同じインスタンスが生成されます (一方、new Xは異なるインスタンスを作成しますnew String)。intern「新しい」文字列を呼び出すと、おそらく同じ効果が見られます。

于 2012-08-27T10:02:38.983 に答える