Luk*_*der 208 java synchronized java-8 jsr335 default-method
在Java 8中,我可以轻松地写:
interface Interface1 {
default void method1() {
synchronized (this) {
// Something
}
}
static void method2() {
synchronized (Interface1.class) {
// Something
}
}
}
Run Code Online (Sandbox Code Playgroud)
我将获得完全同步语义,我也可以在类中使用.但是,我不能synchronized在方法声明上使用修饰符:
interface Interface2 {
default synchronized void method1() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
static synchronized void method2() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我们可以认为,这两个接口的行为方式相同,只是Interface2建立了一个合同上的method1()和method2(),这是比强一点Interface1呢.当然,我们也可能会争辩说default实现不应该对具体实现状态做出任何假设,或者这样的关键字根本不会减轻它的重量.
JSR-335专家组决定不支持synchronized接口方法的原因是什么?
Bri*_*etz 257
虽然起初看起来很明显人们会想要synchronized在默认方法上支持修饰符,但事实证明这样做会很危险,因此被禁止.
同步方法是一种方法的简写,其行为就像整个主体被包含在synchronized其锁定对象是接收器的块中一样.将此语义扩展到默认方法似乎也是明智的; 毕竟,它们也是带接收器的实例方法.(请注意,synchronized方法完全是语法优化;它们不是必需的,它们比相应的synchronized块更紧凑.有一个合理的论据可以说这是一个过早的语法优化,并且同步方法造成比他们解决的问题更多的问题,但很久以前那艘船就航行了.)
那么,他们为什么危险?同步是关于锁定.锁定是关于协调对可变状态的共享访问.每个对象都应该有一个同步策略,用于确定哪些锁保护哪些状态变量.(参见实践中的Java Concurrency,第2.4节.)
许多对象使用Java Monitor Pattern(JCiP 4.1)作为其同步策略,其中对象的状态由其内部锁保护.这个模式没有任何魔力或特殊之处,但它很方便,并且synchronized在方法上使用关键字隐含地假设了这种模式.
拥有该状态的类可以确定该对象的同步策略.但是接口不拥有混合它们的对象的状态.因此,在接口中使用synchronized方法假定一个特定的同步策略,但是你没有合理的假设基础,所以很可能是使用同步不会提供额外的线程安全性(您可能在错误的锁上进行同步).这会给你一种错误的信心,你已经对线程安全做了一些事情,并且没有错误消息告诉你你正在假设错误的同步策略.
为单个源文件持续维护同步策略已经足够困难了; 确保子类正确遵守其超类定义的同步策略更加困难.在这种松散耦合的类(一个接口和可能实现它的许多类)之间尝试这样做几乎是不可能的,而且非常容易出错.
鉴于所有这些论点反对,会有什么争论?看起来他们主要是让界面表现得更像特质.虽然这是一个可以理解的愿望,但默认方法的设计中心是界面演化,而不是"Traits--".在两者可以持续实现的情况下,我们努力做到这一点,但如果一方与另一方发生冲突,我们必须选择支持主要的设计目标.
| 归档时间: |
|
| 查看次数: |
22810 次 |
| 最近记录: |