为什么"synchronized"对多态没有作用

Why "synchronized" has no role in polymorphism

synchronized 不是方法签名的一部分。但是当我们覆盖一个方法时,决定被覆盖的方法是否编译的不仅仅是方法签名。

例如,我们不能添加或扩大检查异常

为什么synchronized对多态没有作用。如果不放置 synchronized,则不应覆盖 synchronized 方法。因为使用 super class 变量的人可能认为所有方法都是线程安全的。

但是应该允许使用 synchronized 覆盖非同步方法,因为它添加了更多功能,但另一方面用户不会遇到任何错误,除了时间延迟。

我正在寻找一个合乎逻辑的解释,它可以为 "why is designed so" 提供一些线索。

A "synchronized" method should not be overridden without putting "synchronized".

错了。 base class 可能不是线程安全的,但是 subclass 可能有自己的同步,例如锁,无锁线程安全数据结构等。不是所有线程安全的方法都是同步的,并不是所有的同步方法都是线程安全的。

反之亦然(但可能会违反其他原则,视情况而定)

synchronized 不是面向对象的东西,而是 runtime/execution 现象和实现细节。它所做的只是 acquire a monitorsynchronized(this){ } 相同的方式(或者在 java.lang.Class 对象上同步,如果是静态的)。作为实现细节,将其暴露给 OOP 考虑是没有意义的。

注意:这并不意味着 @ThreadSafe 之类的编译时注释没有意义。它确实如此,因为它引用方法的契约是线程安全的。 synchronized 不会这样做。

您可以看到 JDK-4294756 的解释,一个方法可以在不保留 synchronized 修饰符的情况下覆盖另一个方法。此错误报告要求编译器在方法重写 synchronized 方法但未声明自身 synchronized 时显示警告,并作为 "Won't Fix" 关闭。关键原因如下:

The use of the synchronized modifier, as well as other synchronization via explicit 'synchronized' statements, is a part of the implementation of an abstraction represented by a class, and an alternate implementation captured in a subclass may use a different synchronization strategy in order to implement equivalent semantics. As an example, consider the case in which a small critical section (protected by a 'synchronized' statement) within a larger unsynchronized method replaces a smaller method that was protected in its entirety by a synchronized method modifier.

因此缺少 synchronized 修饰符并不一定意味着该方法不是线程安全的。线程安全可以在方法内部细化。

让我换一种说法:

假设我们有两个 classes:

class Foo {
    public synchronized void doSomething(...) { ... }
}

class Bar extends Foo {
    public void doSomething(...) { ... }
}

FooBar 不同 class。 foo.doSomething(...)bar.doSomething(...) 是不同的方法。

synchronized 关键字不是为了调用者的利益而存在的:它没有说明 foo.doSomething(...) 做什么 synchronized 关键字只是该方法如何 实现 .

的详细信息

Foo class 需要同步其 doSomething(...) 方法,以便在多线程环境中正确履行其 API 契约。 bar.doSomething(...) 方法的实现方式不同,不需要同步。

只要 Bar 实例可以用在任何需要 Foo 实例的地方,每个人都应该高兴。调用者没有理由希望方法同步:调用者应该只希望方法 work.