あるクラスに同期されたメソッドがあるとしましょう:
abstract class Foo {
public synchronized void foo() { // synchronized!
// ...
};
}
そして私はそれを上書きしましたなし同期修飾子を使用して
class Bar extends Foo {
@Override
public void foo() { // NOT synchronized!
super.foo();
// ...
}
}
このシナリオに関していくつか質問があります。
super
- callは同期されますか?super
- callがない場合、何か同期されますか?synchronized
を使用するように強制する方法はありますか?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() {
// ...
}
いつものように、サブクラス化よりも委任のほうがよいでしょう。
同期メソッドをオーバーライドするときに同期を使用しないと、ランタイムバグが発生する可能性があります。安全策として、この状態を検出するためにオンにできるEclipseチェッカーがあります。デフォルトは「無視」です。 「警告」も有効な選択肢です。
これはこのメッセージを生成します: