synchronized不能用于接口默认方法,语法禁止;在抽象类中仅对具体方法有效,抽象方法上添加无实际同步作用。

synchronized 不能用于接口的默认方法,也不能直接修饰抽象类中的抽象方法(语法上允许但无实际意义),但它可以安全、有效地用在抽象类的具体方法中——包括被子类继承后仍保持同步语义的方法。
接口默认方法不支持 synchronized
Java 接口中的默认方法(default)本质上是实例方法,但 JVM 规范明确禁止在接口方法声明中使用 synchronized。编译器会直接报错:
原因在于:接口不承载状态,也不拥有实例锁(this 指向的是实现类对象,而接口本身无法控制该对象的锁行为),强行加锁会导致语义模糊且不可控。若需同步逻辑,应将临界操作移至实现类中,并在实现类里用 synchronized 或其他并发工具处理。
抽象类中 synchronized 的正确用法
抽象类支持 synchronized,但必须区分场景:
-
抽象方法上加 synchronized 是合法语法,但无效:它只影响子类重写时的“建议”——子类方法不会自动继承该修饰符;即使子类也写了
synchronized,锁对象仍是子类实例(this),与父类无关。这不是错误,但容易造成“已加锁就安全”的误解。 -
抽象类中的具体方法(含 final 方法)可安全使用 synchronized:锁对象明确(
this对于实例方法,Class.class对于静态方法),子类继承后调用仍受同步保护。 - 推荐模式:在抽象类中定义私有/受保护的 synchronized 辅助方法,供子类通过模板方法模式调用。例如:
public abstract class Counter {
protected int count = 0;
// 同步的模板方法,子类可扩展逻辑但不破坏同步
public final void increment() {
doIncrement(); // 子类可重写 doIncrement,但必须保证线程安全
}
// 受保护的同步方法,子类可复用或覆盖
protected synchronized void doIncrement() {
count++;
}
}
关键注意事项
- 子类重写父类的
synchronized方法时,不会自动继承 synchronized 语义,必须显式加上关键字,否则失去同步保障。 - 若抽象类中操作的是 静态共享资源(如全局计数器),应使用
static synchronized方法,锁对象为Counter.class,确保所有子类实例共用同一把类锁。 - 避免用
this作为锁去保护静态字段,或用Class.class去保护实例字段——锁粒度与数据范围错配是常见并发 bug 根源。 - 更灵活、可测试的替代方案:抽象类中定义
protected final Object lock = new Object();,再在synchronized(lock)块中操作共享状态,避免隐式依赖this锁。
小结
接口默认方法禁用 synchronized,抽象类中应优先在具体方法或同步代码块中使用它,锁对象要与共享数据的生命周期和作用域严格匹配。抽象方法上加 synchronized 不报错但不生效,真正起作用的是子类实现中明确写出的同步机制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











