synchronized锁静态方法和实例方法本质不同:静态方法锁类的Class对象,实例方法锁this对象;二者互不干扰,需根据共享资源类型选择对应锁对象。

synchronized 锁静态方法和实例方法,本质是锁不同的对象:静态方法锁的是类的 Class 对象,实例方法锁的是当前调用该方法的对象(this)。理解这个区别,才能避免误以为“加了 synchronized 就一定线程安全”。
锁静态方法:锁的是类对象(Class)
当 synchronized 修饰静态方法时,JVM 会把该类的 Class 对象作为锁。所有线程调用该类的任意静态同步方法,都必须竞争同一把锁。
示例:
public class Counter {
private static int count = 0;
public static synchronized void increment() {
count++;
}
// 等价写法(显式锁 Class 对象)
public static void increment2() {
synchronized (Counter.class) {
count++;
}
}
}
- 多个线程调用
Counter.increment()会互斥执行 - 即使创建了多个
Counter实例,静态同步方法仍共用一把锁 - 与实例方法的 synchronized 完全不冲突——它们锁的对象不同
锁实例方法:锁的是 this 对象
当 synchronized 修饰普通(非静态)方法时,锁的是调用该方法的那个具体实例,即 this。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
示例:
public class Account {
private int balance = 100;
public synchronized void withdraw(int amount) {
if (balance >= amount) {
balance -= amount;
}
}
// 等价写法(显式锁 this)
public void withdraw2(int amount) {
synchronized (this) {
if (balance >= amount) {
balance -= amount;
}
}
}
}
- 两个线程分别操作
new Account()的不同实例,可以同时进入各自的withdraw(),互不影响 - 只有多个线程操作同一个实例时,才会因争抢
this锁而串行执行 - 注意:若方法内访问的是静态变量,仅锁
this并不能保证对该静态变量的线程安全
静态方法和实例方法之间不会互相阻塞
因为它们锁的对象完全不同:一个锁 Counter.class,一个锁 account1 或 account2 实例。所以以下代码中,线程 A 调用静态方法、线程 B 调用实例方法,完全可并发执行。
Counter.increment(); // 锁 Counter.class new Account().withdraw(10); // 锁某个 Account 实例
- 这是常见误区:以为 “synchronized 方法” 是全局一把锁
- 实际是“每个 synchronized 方法背后都有明确的锁对象”,需看修饰的是静态还是实例方法
- 如果要保护共享的静态资源,必须用静态同步方法或
synchronized(XXX.class)
混合场景下如何正确加锁?
当一个类既有静态共享状态,又有实例状态,且两者存在关联时,需谨慎选择锁对象,避免锁粒度过粗或过细。
- 若操作涉及静态计数器 + 实例字段,建议统一用
Counter.class锁(前提是性能可接受) - 更优做法是拆分关注点:静态逻辑走静态同步,实例逻辑走实例同步,中间通过不可变参数或原子类型传递数据
- 避免在同步块里调用外部可变对象的方法(可能引发死锁或嵌套锁问题)

















