В чем причина, почему «синхронизация» не допускается в методах интерфейса Java 8?

В Java 8 я могу легко написать:

interface Interface1 { default void method1() { synchronized (this) { // Something } } static void method2() { synchronized (Interface1.class) { // Something } } } 

Я получу полную семантику синхронизации, которую я могу использовать и в classах. Однако я не могу использовать synchronized модификатор при объявлении метода:

 interface Interface2 { default synchronized void method1() { // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here } static synchronized void method2() { // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here } } 

Теперь можно утверждать, что оба интерфейса ведут себя одинаково, за исключением того, что Interface2 устанавливает контракт по method1() и method2() , который немного сильнее, чем тот, что используется Interface1 . Конечно, мы можем также утверждать, что реализации по default не должны делать никаких предположений о конкретном состоянии реализации или что такое ключевое слово просто не потянет его вес.

Вопрос:

По какой причине экспертная группа JSR-335 решила не поддерживать synchronized по методам интерфейса?

    Это было преднамеренное решение, а не упущение (как было предложено в другом месте). Хотя сначала может показаться очевидным, что нужно поддерживать synchronized модификатор по методам по умолчанию, оказывается, что это будет опасно, и поэтому было запрещено.

    Синхронизированные методы являются сокращением для метода, который ведет себя так, как будто все тело заключено в synchronized блок, объектом блокировки которого является приемник. Может показаться разумным распространить эту семантику на методы по умолчанию; в конце концов, это методы экземпляра с приемником. (Обратите внимание, что synchronized методы полностью синтаксической оптимизации, они не нужны, они просто более компактны, чем соответствующий synchronized блок. Существует разумный аргумент в пользу того, что это преждевременная синтаксическая оптимизация в первую очередь, и что синхронизированные методы вызывают больше проблем, чем они решают, но этот корабль давно отплыл.)

    Итак, почему они опасны? Синхронизация – это блокировка. Блокировка – это согласование общего доступа к изменяемому состоянию. Каждый объект должен иметь политику синхронизации, которая определяет, какие блокировки защищают переменные состояния. (См. Java Concurrency на практике , раздел 2.4.)

    Многие объекты используют в качестве своей политики синхронизации шаблон монитора Java (JCiP 4.1), в котором состояние объекта защищено его встроенной блокировкой. В этом шаблоне нет ничего волшебного или особого, но это удобно, и использование synchronized ключевого слова на методах неявно предполагает этот шаблон.

    Это class, которому принадлежит государство, которое получает определение политики синхронизации этого объекта. Но интерфейсы не владеют состоянием объектов, в которые они смешаны. Таким образом, использование синхронизированного метода в интерфейсе предполагает определенную политику синхронизации, но тот, который у вас нет разумной основы для принятия, поэтому вполне может быть, что использование синхронизации не обеспечивает дополнительной безопасности streamа (вы можете синхронизировать с неправильной блокировкой). Это даст вам ложное чувство уверенности в том, что вы что-то сделали с безопасностью streamов, и никакое сообщение об ошибке не говорит вам о том, что вы принимаете неправильную политику синхронизации.

    Уже достаточно сложно последовательно поддерживать политику синхронизации для одного исходного файла; еще труднее обеспечить, чтобы подclass правильно придерживался политики синхронизации, определяемой ее суперclassом. Попытка сделать это между такими свободно связанными classами (интерфейс и, возможно, многие classы, которые его реализуют) были бы почти невозможными и с высокой степенью подверженности ошибкам.

    Учитывая все эти аргументы против, для чего будет аргумент? Похоже, что они в основном связаны с тем, что интерфейсы ведут себя скорее как черты. Хотя это понятное желание, дизайн-центр для методов по умолчанию – это эволюция интерфейса, а не «Черты–». Там, где эти два варианта могли быть последовательно достигнуты, мы стремились сделать это, но там, где один из них противоречит другому, нам пришлось выбирать в пользу основной цели проекта.

    Давайте будем гением компьютера.