synchronized修饰静态方法时锁的是当前类的Class对象,因为静态方法属于类而非实例,JVM中每个类有唯一Class实例,故所有调用共享同一把类锁。

synchronized 修饰静态方法时,锁的是该类的 Class 对象,也就是类级别的锁,所有该类的实例共享同一把锁。
为什么静态方法锁的是 Class 对象?
静态方法属于类本身,不依赖于任何实例。JVM 在加载类时会为每个类创建唯一的 Class 实例(如 MyClass.class),synchronized 静态方法底层等价于:
synchronized (MyClass.class) { ... }
因此,无论多少个对象调用这个静态同步方法,都必须竞争同一把锁 —— 即 MyClass.class。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。
和普通 synchronized 实例方法的区别
- 实例方法锁的是 当前对象(this):不同对象调用互不影响
- 静态方法锁的是 类对象(MyClass.class):所有线程串行执行,不管调用者是哪个实例或是否通过类名直接调用
实际写法和效果示例
下面两种写法效果完全一样:
public class Counter {
private static int count = 0;
// 写法1:用 synchronized 修饰静态方法
public static synchronized void increment() {
count++;
}
// 写法2:手动同步 Class 对象(等效)
public static void increment2() {
synchronized (Counter.class) {
count++;
}
}
}
即使有多个线程分别调用 new Counter().increment() 或 Counter.increment(),都会被阻塞排队执行。
注意事项
- 静态同步方法和实例同步方法 不会互相阻塞:一个线程在执行静态同步方法,另一个仍可进入某个对象的实例同步方法
- 若需同时控制类级和实例级访问,应显式使用
Counter.class或this同步块,避免混淆 - 反射获取的
Class对象是唯一的,所以通过obj.getClass()获取再加锁,也等同于锁类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










