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()上建立contract,这比Interface1有点强。当然,我们也可能会认为default实现不应该对具体的实现状态做任何假设,或者这样的关键字根本不会减轻其重量。

题:

JSR-335专家组决定不支持synchronized接口方法的原因是什么?
 注意,在这个问题急切关闭之前:适应Stack Overflow的问答格式:我只是在寻找权威的引用,而不是投机。这个问题的权威回答可能会帮助未来的访问者解决这个问题,所以请do not close it eagerly

回答:

这是一个故意的决定,而不是一个遗漏(如其他地方所建议的)。起初,似乎很明显,人们希望支持默认方法的synchronized修饰符,结果是这样做是危险的,所以被禁止。
同步方法是一种方法的简写,该方法的行为就好像整个身体被封装在其对象为接收者的synchronized块中。将这种语义扩展到默认方法似乎也是合理的;毕竟,它们也是接收器的实例方法。 (请注意,synchronized方法完全是一种句法优化;它们不是必需的,它们比相应的synchronized块更紧凑,有一个合理的论据,这是第一次的早期语法优化而且同步的方法会导致比他们解决的更多的问题,但是这艘船很久以前就航行了。)
那么为什么他们很危险?同步是关于锁定。锁定是关于协调对可变状态的共享访问。每个对象都应该有一个同步策略来确定哪个锁保护哪些状态变量。 (见Java Concurrency in Practice,第2.4节。)
许多对象使用Java Monitor Pattern(JCiP 4.1)作为其同步策略,其中对象的状态由其内在锁定保护。这种模式没有任何魔法或特殊的东西,但它是方便的,使用synchronized关键字的方法隐含地假定这种模式。
拥有状态以确定该对象的同步策略的类是该类。但接口不拥有混合到其中的对象的状态。因此,在接口中使用synchronized方法假定特定的同步策略,但是您没有合理的假设依据,所以可能情况下同步的使用不会提供额外的线程安全性(您可能会在错误的锁上同步)。这将给你一个虚假的信心,你已经做了一些关于线程安全,没有错误信息告诉你,你假设错误的同步策略。
一直保持单个源文件的同步策略已经很困难了;确保一个子类正确遵守由其超类定义的同步策略更加困难。尝试在这样松散耦合的类(一个接口和可能许多实现它的类)之间这样做是几乎不可能的,并且容易出错。
鉴于所有这些反对的论据,有什么论据呢?它似乎主要是使界面的行为更像特质。虽然这是一个可以理解的愿望,默认方法的设计中心是界面演变,而不是“特征”。两者可以一致地实现,我们力求做到这一点,但与另一方冲突的是,我们必须选择主要的设计目标。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: What is the reason why “synchronized” is not allowed in Java 8 interface methods?

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

74 − = 71