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

Почему абстрактный метод не может быть синхронизирован?

Я читал поток от CodeRanch, говорящий, что абстрактные методы не могут быть синхронизированы из-за того, что абстрактный класс не может быть создан, что означает отсутствие объекта для блокировки.

Это не имеет смысла, поскольку абстрактный класс является определением (контрактом) для дочернего класса. Абстрактное определение синхронизированного метода не нужно блокировать, это делает ребенок. Весь абстрактный заголовок указывает, что дочерний элемент должен синхронизировать этот метод. Является ли моя логика правильной? Если нет, кто-нибудь может объяснить, почему я ошибаюсь?

4b9b3361

Ответ 1

Комментарий о невозможности создания абстрактного класса - это мусор. Учитывая, что он должен быть методом экземпляра абстрактным, существует определенная ссылка, которая может быть заблокирована. Конкретные методы в абстрактных классах могут относиться к this. Однако это еще не означает, что абстрактные классы должны быть синхронизированы.

Независимо от того, синхронизирован ли метод, это деталь реализации метода. Синхронизация не указывается нигде как декларативный контракт - это не так, как вы можете синхронизировать в интерфейсах.

Как класс реализует любые гарантии безопасности потоков, которые он предоставляет, зависит от него. Если абстрактный класс хочет задать конкретный подход, он должен использовать шаблон метода шаблона:

// I hate synchronizing on "this"
private final Object lock = new Object();

public final void foo() {
    synchronized(lock) {
        fooImpl();
    }
}

protected abstract void fooImpl();

Это довольно опасно, хотя, учитывая, что он эффективно вызывает "неизвестный" код внутри блокировки, который является рецептом взаимоблокировок и т.д.

Ответ 2

Извините, это не имеет смысла, просто как это работает. Поведение блокировки не может быть задано с использованием абстрактных методов или методов интерфейса, это не является частью контракта. Вероятно, идея заключалась в том, что поведение блокировки в корне является частью реализации - разные реализации захотят выполнить блокировку по-разному - и было бы чрезмерным указывать ее на этом уровне абстракции.

Ответ 3

synchronized void foo()
{
    body
}

определяется как эквивалентное

void foo()
{ 
    synchronized(this)
    {
        body
    }
}

(если статический, синхронизированный в классе вместо this)

Поскольку абстрактный метод не имеет тела, ключевое слово synchronized в методе undefined.

Ответ 4

Я думаю, что одна логика в этом может заключаться в том, следует ли или нет синхронизировать этот метод с помощью класса реализации. Смысл, это дает свободу разработчику выбирать, предоставлять ли синхронизированную или несинхронизированную реализацию. Кроме того, у клиента также будет возможность выбрать несинхронизированную версию, чтобы избежать накладных расходов на синхронизацию, если безопасность потоков не является проблемой.