synchronized
不是方法签名的一部分。但是当我们覆盖一个方法时,它不仅是方法签名,它决定了被覆盖的方法是否会被编译。
例如,我们无法添加或扩大已检查的异常
为什么synchronized
在多态性中没有作用。如果不放synchronized
,则不应覆盖synchronized
方法。因为使用超类变量的人可能认为所有方法都是线程安全的。
但是,应该允许使用synchronized
覆盖非同步方法,因为它会添加更多功能,但另一方面,除了时滞之外,用户不会遇到任何错误。
我正在寻找一个合乎逻辑的解释,它可以为#34;设计如此"。
答案 0 :(得分:9)
A"同步"如果没有放置" synchronized"。
,则不应覆盖该方法
错误。基类可能不是线程安全的,但子类可能有自己的同步,例如锁,无锁线程安全数据结构等。并非所有线程安全方法都是同步的,并非全部synchronized方法是线程安全的。
同样可以朝另一个方向发展(但可能会违反其他原则,视具体情况而定)
synchronized
不是一个面向对象的东西,而是一个运行时/执行现象,以及一个实现细节。它所做的全部是acquire a monitor,方式synchronized(this){ }
(或者如果是静态的话,在java.lang.Class对象上进行同步)。作为一个实现细节,将它暴露给OOP考虑是没有意义的。
注意:这并不意味着编译时注释(例如@ThreadSafe
)没有意义。确实如此,因为它引用了方法的合同是线程安全的。 synchronized
没有这样做。
答案 1 :(得分:5)
您可以看到JDK-4294756的解释,但是如果方法在不保留synchronized
修饰符的情况下覆盖其他方法,则可以。当一个方法覆盖synchronized
方法但没有声明自己synchronized
时,此错误报告要求编译器显示警告,并且它已关闭为"赢得&#t; t修复& #34 ;.关键原因如下:
使用synchronized修饰符,以及其他同步通道 明确的同步'声明,是执行的一部分 由类表示的抽象,以及捕获的替代实现 在子类中可以使用不同的同步策略 实现等效的语义。作为一个例子,考虑一下a的情况 较小的临界区(受同步的语句保护) unsynchronized方法替换了一个受其保护的较小方法 整数由同步方法修饰符。
因此缺少synchronized
修饰符并不一定意味着该方法不是线程安全的。线程安全可以在方法中细化。
答案 2 :(得分:1)
让我用不同的方式:
假设我们有两个类:
class Foo {
public synchronized void doSomething(...) { ... }
}
class Bar extends Foo {
public void doSomething(...) { ... }
}
Foo
和Bar
是不同的类。 foo.doSomething(...)
和bar.doSomething(...)
是不同的方法。
synchronized
关键字不适合调用者的利益:它没有说明foo.doSomething(...)
做什么。 synchronized
关键字只是该方法实施的详细信息。
Foo
类需要同步其doSomething(...)
方法才能在多线程环境中正确履行其API协定。 bar.doSomething(...)
方法的实现方式不同,并且不需要同步。
只要Bar
实例可以在需要Foo
实例的地方使用,每个人都应该感到高兴。调用者没有理由要求同步方法:调用者应该只希望方法工作。