java 中子类可以重写父类的同步方法。重写的核心在于方法签名(名称和参数列表)必须一致,而访问修饰符和异常声明需符合规范。虽然父类方法带有 synchronized 关键字,但子类在重写时可以选择保留该关键字以维持同步行为,也可以移除它以实现非同步的重写版本。需要注意的是,如果子类移除了 synchronized,则调用该方法时将不再获取对象锁,这可能导致线程安全问题;反之,若子类重新添加 synchronized,则默认锁定的是当前子类实例(this),而非父类实例。

重写时是否必须保留 synchronized 关键字
子类重写父类同步方法时,不需要也不强制要求保留 synchronized 关键字。开发者可以根据业务需求决定子类方法是否需要同步。如果子类方法不需要互斥访问共享资源,可以直接去掉该关键字,从而允许并发执行,提高性能。但如果子类方法内部操作了共享状态,建议显式加上 synchronized 以保证线程安全。无论是否保留,方法的重写规则(如不能降低访问权限、抛出受检异常需更窄等)依然适用。

public class Parent {
public synchronized void doWork() {
System.out.println("Parent work");
}
}
public class Child extends Parent {
// 选项1:保留同步
@Override
public synchronized void doWork() {
super.doWork();
System.out.println("Child specific work");
}
// 选项2:移除同步
// @Override
// public void doWork() {
// super.doWork();
// System.out.println("Child specific work");
// }
重写后锁定的对象是谁
当子类重写父类同步方法并保留 synchronized 关键字时,锁定的对象始终是调用该方法的具体实例(即 this)。这意味着,如果通过父类引用指向子类对象来调用方法,锁住的依然是子类实例。这种机制确保了多态性下的同步语义一致性。然而,如果父类和子类各自定义了不同的同步方法,它们可能锁定不同的对象或同一对象的不同部分,需仔细设计以避免死锁或竞态条件。对于静态同步方法,则锁定的是 Class 对象,与实例无关。

public class TestSync {
public static void main(String[] args) {
Parent p = new Child();
// 调用的是 Child 的 doWork()
// 如果 Child.doWork() 是 synchronized,则锁定 Child 实例
p.doWork();
}
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











