49

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

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

同期修飾子を使用せずにオーバーライドしました:

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

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

  1. オーバーライドされたメソッドも暗黙的に同期されますか?
  2. そうでない場合、super呼び出しは同期されますか?
  3. -callがない場合super、何かが同期されますか?
  4. オーバーライド メソッドを強制的に使用する方法はありますsynchronizedか (インターフェイス内の抽象メソッド定義またはメソッド定義では、synchronized キーワードが許可されていないことに気付きました)。
4

2 に答える 2

55
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() {
    // ...
}

これまでと同様に、サブクラス化よりも委譲を使用したほうがよい場合があります。

于 2013-03-12T23:56:49.753 に答える
22

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

次のメッセージが生成されます。

ここに画像の説明を入力

ここに画像の説明を入力

于 2013-03-13T00:13:19.157 に答える