49

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

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

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

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

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

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

2 回答 2

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

本质上是一样的:

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

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

所以: 1. 没有。 2. 是的。3. No. 4. 标记方法final并调用protected可能被覆盖的方法。

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

与以往一样,使用委托而不是子类化可能会更好。

于 2013-03-12T23:56:49.753 回答
22

在覆盖同步方法时未能使用同步有可能导致运行时错误。作为安全措施,您可以打开一个 Eclipse 检查器来检测这种情况。默认为“忽略”。“警告”也是一个有效的选择。 优先

这将产生此消息:

在此处输入图像描述

在此处输入图像描述

于 2013-03-13T00:13:19.157 回答