web-dev-qa-db-ja.com

Javaでの同期されたメソッドのオーバーライド

あるクラスに同期されたメソッドがあるとしましょう:

abstract class Foo {
    public synchronized void foo() {  // synchronized!
        // ...
    };
}

そして私はそれを上書きしましたなし同期修飾子を使用して

class Bar extends Foo {
    @Override
    public void foo() {               // NOT synchronized!
        super.foo();
        // ...
    }
 }

このシナリオに関していくつか質問があります。

  1. オーバーライドされたメソッドも暗黙的に同期されますか?
  2. そうでない場合、super- callは同期されますか?
  3. super- callがない場合、何か同期されますか?
  4. オーバーライドするメソッドがsynchronizedを使用するように強制する方法はありますか?
46
Markus A.
public synchronized void foo() {  // synchronized!
    // ...
};

本質的に同じです:

public void foo() {
    synchronized (this) {  // synchronized!
        // ...
    }
};

後者はより明確であるため、通常はその形式を使用することをお勧めします。または、「外部」オブジェクトの代わりにプライベートフィールドであるロックを使用することをお勧めします。

つまり:1.いいえ。2.はい。 3.いいえ。4.メソッドfinalをマークし、オーバーライドできるprotectedメソッドを呼び出します。

public final void foo() {
    synchronized (this) {
        fooImpl();
    }
};
protected void fooImpl() {
    // ...
}

いつものように、サブクラス化よりも委任のほうがよいでしょう。

49

同期メソッドをオーバーライドするときに同期を使用しないと、ランタイムバグが発生する可能性があります。安全策として、この状態を検出するためにオンにできるEclipseチェッカーがあります。デフォルトは「無視」です。 「警告」も有効な選択肢です。 preferences

これはこのメッセージを生成します:

enter image description here

enter image description here

23
Java42