在Java 8接口方法中不允许“synchronized”的原因是什么? [英] What is the reason why “synchronized” is not allowed in Java 8 interface methods?

查看:1827
本文介绍了在Java 8接口方法中不允许“synchronized”的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java 8中,我可以轻松地写:

In Java 8, I can easily write:

interface Interface1 {
    default void method1() {
        synchronized (this) {
            // Something
        }
    }

    static void method2() {
        synchronized (Interface1.class) {
            // Something
        }
    }
}

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

I will get the full synchronisation semantics that I can use also in classes. I cannot, however, use the synchronized modifier on method declarations:

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

    static synchronized void method2() {
        // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }
}

现在,可以说两个接口的行为方式相同,只不过 Interface2 method1() method2()上建立合约,这是比 Interface1 更强一些。当然,我们也可能会认为默认实现不应该对具体的实现状态做出任何假设,或者这样的关键字根本不会影响它的重量。

Now, one can argue that the two interfaces behave the same way except that Interface2 establishes a contract on method1() and on method2(), which is a bit stronger than what Interface1 does. Of course, we might also argue that default implementations should not make any assumptions about concrete implementation state, or that such a keyword simply wouldn't pull its weight.

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

What is the reason why the JSR-335 expert group decided not to support synchronized on interface methods?

推荐答案

这是一个刻意的决定,而不是遗漏(如同在其他地方建议。)虽然起初看起来很明显,人们会想要在默认方法上支持 synchronized 修饰符,但事实证明这样做会很危险,所以禁止。

This was a deliberate decision, rather than an omission (as has been suggested elsewhere.) While at first it might seem obvious that one would want to support the synchronized modifier on default methods, it turns out that doing so would be dangerous, and so was prohibited.

同步方法是一种方法的简写,其行为就像整个主体被包含在 synchronized 块中一样锁定对象是接收者。将此语义扩展到默认方法似乎也是明智的;毕竟,它们也是带接收器的实例方法。 (注意 synchronized 方法完全是语法优化;它们不是必需的,它们比相应的 synchronized block。有一个合理的论据是,这首先是一个过早的语法优化,并且同步方法会导致比他们解决的更多问题,但是很久以前这艘船已经航行了。)

Synchronized methods are a shorthand for a method which behaves as if the entire body is enclosed in a synchronized block whose lock object is the receiver. It might seem sensible to extend this semantics to default methods as well; after all, they are instance methods with a receiver too. (Note that synchronized methods are entirely a syntactic optimization; they're not needed, they're just more compact than the corresponding synchronized block. There's a reasonable argument to be made that this was a premature syntactic optimization in the first place, and that synchronized methods cause more problems than they solve, but that ship sailed a long time ago.)

那么,为什么它们很危险?同步是关于锁定。锁定是关于协调对可变状态的共享访问。每个对象都应该有一个同步策略,用于确定哪些锁保护哪些状态变量。 (参见 Java Concurrency in Practice ,第2.4节。)

So, why are they dangerous? Synchronization is about locking. Locking is about coordinating shared access to mutable state. Each object should have a synchronization policy that determines which locks guard which state variables. (See Java Concurrency in Practice, section 2.4.)

许多对象使用 Java Monitor Pattern (JCiP 4.1)作为其同步策略,其中对象的状态由其内部锁保护。这种模式没有任何魔力或特殊之处,但它很方便,并且在方法上使用 synchronized 关键字隐含地假设这种模式。

Many objects use as their synchronization policy the Java Monitor Pattern (JCiP 4.1), in which an object's state is guarded by its intrinsic lock. There is nothing magic or special about this pattern, but it is convenient, and the use of the synchronized keyword on methods implicitly assumes this pattern.

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

It is the class that owns the state that gets to determine that object's synchronization policy. But interfaces do not own the state of the objects into which they are mixed in. So using a synchronized method in an interface assumes a particular synchronization policy, but one which you have no reasonable basis for assuming, so it might well be the case that the use of synchronization provides no additional thread safety whatsoever (you might be synchronizing on the wrong lock). This would give you the false sense of confidence that you have done something about thread safety, and no error message tells you that you're assuming the wrong synchronization policy.

为单个源文件持续维护同步策略已经足够困难了;确保子类正确遵守其超类定义的同步策略更加困难。在这种松散耦合的类(接口和可能实现它的许多类)之间尝试这样做几乎是不可能的,而且非常容易出错。

It is already hard enough to consistently maintain a synchronization policy for a single source file; it is even harder to ensure that a subclass correctly adhere to the synchronization policy defined by its superclass. Trying to do so between such loosely coupled classes (an interface and the possibly many classes which implement it) would be nearly impossible and highly error-prone.

鉴于所有这些论点反对,会有什么参数?看起来他们主要是让界面表现得更像特质。虽然这是一个可以理解的愿望,但默认方法的设计中心是界面演化,而不是Traits--。在两者可以持续实现的情况下,我们努力做到这一点,但是如果一方与另一方发生冲突,我们必须选择支持主要的设计目标。

Given all those arguments against, what would be the argument for? It seems they're mostly about making interfaces behave more like traits. While this is an understandable desire, the design center for default methods is interface evolution, not "Traits--". Where the two could be consistently achieved, we strove to do so, but where one is in conflict with the other, we had to choose in favor of the primary design goal.

这篇关于在Java 8接口方法中不允许“synchronized”的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆