类锁和对象锁作用目标不同、互不干扰:类锁锁定Class对象,对象锁锁定实例,二者可共存于同一类中,但不能同时作用于同一方法。

类锁和对象锁不能“同时作用于同一个方法”,因为它们作用的目标根本不同:一个锁的是类(Class对象),一个锁的是实例(this或任意对象)。但你可以让一个类中**既有被类锁保护的静态方法,又有被对象锁保护的实例方法**,二者并存、互不干扰——这才是实际开发中常见的“同时存在”场景。
类锁只作用于静态方法或 Class 对象
类锁本质是锁住该类的 Class 对象(如 MyClass.class),它对所有线程全局唯一。以下写法都触发类锁:
public static synchronized void doStatic() { ... }synchronized(MyClass.class) { ... }
一旦某个线程进入这类代码,其他线程无法再进入任何同样以 MyClass.class 为锁的同步块或静态同步方法,但完全不影响它们调用该类的任意实例方法(无论是否加锁)。
对象锁只作用于实例方法或指定对象
对象锁默认锁定当前实例(this),每个对象有独立的锁。以下写法都触发对象锁:
立即学习“Java免费学习笔记(深入)”;
public synchronized void doInstance() { ... }synchronized(this) { ... }-
synchronized(someObj) { ... }(锁的是someObj实例)
两个不同对象调用各自的 doInstance(),彼此不阻塞;但同一对象被多个线程调用时,会排队等待对象锁释放。
类锁和对象锁互不干扰
这是关键点:获取类锁不会阻塞对象锁,反之亦然。例如:
- 线程 A 正在执行
MyClass.doStatic()(持有类锁)→ 线程 B 仍可立刻调用new MyClass().doInstance()(只需拿到那个实例的对象锁) - 线程 C 正在执行
obj.doInstance()(持有obj的对象锁)→ 线程 D 仍可立刻调用MyClass.doStatic()(只需拿到类锁)
它们锁的是不同内存地址(MyClass.class vs obj),JVM 也完全分开管理。
为什么不能在一个方法上“同时用两种锁”?
语法上不允许,逻辑上也没意义:
-
static synchronized方法 → 锁的是类,不是实例,this在静态上下文中不可用 - 普通
synchronized方法 → 锁的是实例,而静态方法没有实例上下文 -
synchronized(this)块在静态方法里编译失败,因为this不存在
强行混用会导致编译错误或语义混乱,不是设计意图。


















