【问题标题】:Overriding synchronized methods in Java在 Java 中重写同步方法
【发布时间】:2013-02-28 18:01:05
【问题描述】:

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

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(我注意到接口内的抽象方法定义或方法定义不允许使用同步关键字)?

【问题讨论】:

标签: java overriding synchronized


【解决方案1】:
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() {
    // ...
}

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

【讨论】:

  • 使用 fooImpl 是正确的方法,仍然提醒我ClassLoader.loadClassInternal 当然可以通过monitorExit / moniorEnter 在 fooImpl 中作弊
  • @bestss 即使您编写自己的字节码,也应该匹配监视器进入/退出。 (IIRC 在规范中有一些特殊的余地,但没有任何合理的实现。)虽然fooImpl 可以wait
  • 除非它是相当新的变化(并且您的意思是在相同的方法中),否则情况并非如此,即使是偏向锁定也必须考虑不平衡的进入/退出。如果您调用wait,则需要另一个线程来执行代码。否则它只是调用循环monitorExit 直到IllegalMonitorStateException 并计数然后monitorEnter。嗯,真的要检查规格。
  • 找到它:Structured locking 这是非强制性的。看来这个词是用 java se7 创造的,或者至少找不到以前的参考资料。
【解决方案2】:

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

将产生此消息:

【讨论】:

  • 旧答案,但您应该解释您的断言,即未能同步覆盖可能会导致错误。解释如何在开发环境中标记这些很有趣,但不是答案(任何问题,更不用说 OP 4)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多