Переопределение синхронизированных методов в Java
Скажем, у меня есть синхронизированный метод для некоторого класса:
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
(я заметил, что абстрактные определения методов или определения методов внутри интерфейса не позволяют синхронизировать ключевое слово)?
Ответы
Ответ 1
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() {
// ...
}
Как всегда, вам может быть лучше с делегацией, а не с подклассом.
Ответ 2
Невозможность использования синхронизации при переопределении синхронизированного метода может вызвать ошибки времени выполнения. В качестве защиты есть средство проверки Eclipse, которое вы можете включить, чтобы обнаружить это условие.
По умолчанию "ignore". "Предупреждение" также является допустимым выбором.
![preferences]()
который выдает это сообщение:
![enter image description here]()
![enter image description here]()