5

次のコードではどうなりますか? 同期は機能しますか?これはインタビューの質問です。

class T
{
    public static void main(String args[])
    {
        Object myObject = new Object();
        synchronized (myObject)
        {
            myObject = new Object();
        } // end sync
    }
}
4

6 に答える 6

4

同期ブロックに入るたびに、別のオブジェクトで同期します。ほとんどの場合、これは混乱を招く以外には何もしませんが、2 つのスレッドが同じオブジェクトを見て待機する可能性がわずかにあります。

このため、 ではないフィールドで同期している場合、コード アナライザーは警告を出しますfinal

于 2012-06-21T08:59:44.457 に答える
1

取得した同じモニターを引き続き解放しますが、使用をロックする他のコードmyObject(ローカル変数であるため、ここでは不可能であり、同期が基本的に無意味になります) は、新しいオブジェクトの使用を開始します。

変数ではなく、オブジェクト(または、オブジェクトに関連付けられたモニター)に同期が適用されることを忘れないでください。取得/解放されるモニターは、同期ブロックの開始に達したときの式の値に依存します。式は、同期ブロックの最後で再評価されません。

于 2012-06-21T08:58:47.160 に答える
0

最初にmyObjectのロックを取得する必要があります。このロックがブロックされている場合は、ロックが解除されるまで待つ必要があります。

同期にはマルチスレッド環境が必要ですが、コードは並行とは関係がないようですので、何も起こらないと申し訳ありません。

于 2012-06-21T09:06:05.423 に答える
0

コードを実行し、結果を分析します。

public class Test {
    static Foo o = new Foo(0);
    static class Foo {
        private int i = 0;
        Foo(int i) {
            this.i = i;
        }
        public void addOnce() {
            this.i++;
        }
        public String toString() {
            return String.valueOf(i);
        }
    }
    public static void main(String args[]) {
        test1();
        try {Thread.sleep(10000);} catch (Exception e) {}
        test2();
    }
    public static void test1() {
        Runnable r = new Runnable() {
            public void run() {
                synchronized (o) {
                    System.out.println("1------>"+o);
                    o = new Foo(1);
                    try {Thread.sleep(3000);} catch (Exception e) {}
                    System.out.println("1------>"+o);
                }
            }
        };
        new Thread(r).start();
        new Thread(r).start();
    }
    public static void test2() {
        Runnable r = new Runnable() {
            public void run() {
                synchronized (o) {
                    System.out.println("2------>"+o);
                    o.addOnce();
                    try {Thread.sleep(3000);} catch (Exception e) {}
                    System.out.println("2------>"+o);
                }
            }
        };
        new Thread(r).start();
        new Thread(r).start();
    }
}
于 2012-06-21T09:23:56.890 に答える
0

オブジェクトはどのスレッドでも共有されていないため、このコードの背後にある理由はわかりません。同期ブロックを削除しても、実際の結果には何の影響もありません。コードの実行が速くなるだけです

于 2012-06-21T09:03:42.023 に答える
0

いいえ、うまくいきません。新しいスレッドが入るたびに、新しいスレッドmyObjectが作成されます。特に今myObjectはローカル変数です!

myObjectロックしているオブジェクトを変更するため、クラスメンバーであっても機能しません。詳細な説明については、non-final フィールドの同期に関する質問を参照してください。

于 2012-06-21T08:59:08.670 に答える