在 Java 中重写同步方法

2022-08-31 20:58:19

假设我在某个类上有一个同步方法:

abstract class Foo {
    public synchronized void foo() {  // synchronized!
        // ...
    };
}

我在不使用同步修饰符的情况下覆盖了它:

class Bar extends Foo {
    @Override
    public void foo() {               // NOT synchronized!
        super.foo();
        // ...
    }
 }

关于这种情况,我有几个具体问题:

  1. 重写的方法是否也会隐式同步?
  2. 如果没有,-call 是否会同步?super
  3. 如果没有 -call,是否会同步任何内容?super
  4. 有没有办法强制使用重写方法(我注意到接口内的抽象方法定义或方法定义不允许使用synced关键字)?synchronized

答案 1
public synchronized void foo() {  // synchronized!
    // ...
};

本质上与:

public void foo() {
    synchronized (this) {  // synchronized!
        // ...
    }
};

后者更明确,所以我通常建议使用这种形式。或者最好使用私有字段的锁,而不是“外部”对象。

所以:1.2号。是的。3. 第4号。标记该方法并调用可能被重写的方法。finalprotected

public final void foo() {
    synchronized (this) {
        fooImpl();
    }
};
protected void fooImpl() {
    // ...
}

与以往一样,您最好使用委派而不是子类化。


答案 2

在重写同步方法时不使用同步方法可能会导致运行时错误。作为保护措施,您可以打开一个 Eclipse 检查器来检测这种情况。默认值为“忽略”。“警告”也是一个有效的选择。preferences

这将产生以下消息:

enter image description here

enter image description here


推荐