实例方法锁this,各对象互不干扰;静态方法锁class,全类共享一把锁;保护static变量必须用类锁,混用将失效。

关键就一点:锁的对象不同,导致互斥范围完全不同。
实例方法锁的是 this(当前对象)
每个对象实例都有自己的锁。比如你 new 了三个 UserService 对象,那就有三把独立的锁。线程 A 调用 user1.instanceMethod(),线程 B 同时调用 user2.instanceMethod(),完全不冲突——因为锁的不是同一个对象。
- 等价写法是:
synchronized(this) { ... } - 适合保护实例变量(如
private int count;) - 多个实例之间互不影响,锁粒度细、并发性高
静态方法锁的是 Class 对象(如 UserService.class)
整个类只有一把锁,所有实例共享。哪怕你创建了一百个对象,只要有一个线程在执行 staticMethod(),其他任何线程(不管调用哪个实例)都得排队等着。
- 等价写法是:
synchronized(UserService.class) { ... } - 适合保护静态资源(如
private static int globalId;或单例初始化逻辑) - 锁粒度粗,容易成为性能瓶颈,但能确保类级别数据安全
为什么不能混用?常见误区
比如想保护一个 static 变量,却在实例方法上加 synchronized —— 没用。因为每个实例锁的是自己,根本拦不住其他实例去改那个 static 变量。
- 查被保护的数据:是
static的?那就必须用类锁(静态同步或synchronized(XXX.class)) - 看调用场景:如果是 Web 应用里每个请求都 new 一个 service,还用静态同步,很可能把高并发拖慢成串行
- 验证是否真需要全局互斥:有时用
AtomicInteger或ConcurrentHashMap比加锁更轻量
本质不是语法差异,而是 JVM 执行时 monitorenter 指令操作的对象不同:一个是栈顶的 this 引用,一个是通过 ldc 加载的 Class 常量。锁对了对象,才能锁住该锁的事。










