Подтвердить что ты не робот

Переопределение синхронизированных методов в 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 (я заметил, что абстрактные определения методов или определения методов внутри интерфейса не позволяют синхронизировать ключевое слово)?
4b9b3361

Ответ 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