Java 8接口方法中不允许“同步”的原因是什么?

在Java 8中,我可以很容易地写出:

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

我将得到我可以在类中使用的完全同步语义。 但是我不能在方法声明中使用synchronized修饰符:

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

现在,人们可以争辩说,除了Interface2method1()method2()上build立一个契约 ,这个接口的行为方式是相同的,这个Interface2Interface1强。 当然,我们也可能会认为, default实现不应该对具体的实现状态做任何的假设,或者这样的关键字根本就不会做出决定。

题:

JSR-335专家组决定不支持接口方法synchronized的原因是什么?


请注意,在这个问题急切地closures之前 :为了适应Stack Overflow的问答格式:我只是在寻找权威的引用,而不是猜测。 这个问题的权威答案可能会有助于这个问题的未来访问者,所以请不要急于closures它

这是一个蓄意的决定,而不是一个遗漏(正如别处已经提出的那样)。虽然起初似乎很明显,人们会希望在缺省方法上支持synchronized修饰符,但事实certificate这样做会是危险的,所以被禁止。

同步方法是一种方法的缩写,其行为如同整个主体被包含在synchronized块中,其锁对象是接收者。 将这种语义扩展到缺省方法也许是明智的; 毕竟,它们也是带有接收器的实例方法。 (请注意, synchronized方法完全是句法优化;它们不是必需的,它们只比相应的synchronized块更紧凑。有一个合理的理由可以说,这是一个过早的句法优化,同步的方法会造成比他们解决的问题更多的问题,但是这艘船很久以前就航行了。)

那么,他们为什么危险呢? 同步是关于locking。 locking是关于协调对可变状态的共享访问。 每个对象应该有一个同步策略,确定哪些锁保护哪些状态variables。 (请参阅Java并发实践 ,第2.4节。)

Java监视器模式 (JCiP 4.1)使用许多对象作为它们的同步策略,其中对象的状态由其固有的锁保护。 关于这个模式没有什么神奇或者特别的地方,但是它很方便,并且在方法上使用synchronized关键字隐含地假定了这个模式。

它是拥有状态的类来确定对象的同步策略。 但是接口并不拥有它们混入其中的对象的状态。因此,在一个接口中使用一个同步方法假定一个特定的同步策略,但是你没有合理的基础假设,所以很可能是这样的情况同步的使用不会提供任何额外的线程安全性(您可能正在同步错误的locking)。 这会给你错误的自信感,你已经做了一些关于线程安全的事情,没有错误信息告诉你,你正在假设错误的同步策略。

始终如一地维护单个源文件的同步策略已经非常困难; 更难确保一个子类正确地遵守其超类定义的同步策略。 试图在这样的松散耦合的类(一个接口以及可能实现它的许多类)之间这样做几乎是不可能的,并且极易出错。

鉴于所有这些反对的论点,将会有什么争论? 看来他们主要是关于使接口更像特质。 虽然这是一个可以理解的愿望,但默认方法的devise中心是界面的演变,而不是“特质 – ”。 如果能够一致地实现这两个目标,我们就努力做到这一点,但是在与另一个发生冲突的地方,我们不得不select主要的devise目标。