synchronized修饰静态方法锁Class对象,实例方法锁this对象;静态方法保护类共享数据,实例方法保护对象私有状态;混用二者保护同一数据会导致竞态条件。

synchronized 修饰静态方法和实例方法,表面写法相似,实际锁的对象完全不同——这直接决定线程是否真正互斥,也常是并发 bug 的根源。
静态同步方法:锁的是类对象(Class)
所有线程调用该类的任意静态同步方法时,都竞争同一把锁,即 Counter.class 这个 Class 实例。无论创建多少个 Counter 对象,静态方法始终共用这把锁。
- 写法一(隐式):
public static synchronized void increment() { ... } - 写法二(显式):
public static void increment() { synchronized (Counter.class) { ... } },语义完全等价 - 适用场景:操作共享的静态变量(如计数器、单例初始化、配置缓存等)
实例同步方法:锁的是 this 对象
每个对象实例拥有独立的锁。线程 A 调用 obj1.increment(),线程 B 同时调用 obj2.increment(),二者不会阻塞——因为锁的是不同的 this。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 写法:
public synchronized void increment() { ... } - 等价于:
public void increment() { synchronized (this) { ... } } - 适用场景:保护当前对象内部的状态(如实例字段 count、状态标记等)
关键区别不是“静态 or 实例”,而是“锁谁”
二者锁的对象天然隔离:
立即学习“Java免费学习笔记(深入)”;
- 静态方法锁
Counter.class,实例方法锁new Counter()得到的具体对象 - 一个线程在执行静态同步方法,另一个线程完全可以同时执行某个实例的同步方法——它们不抢同一把锁
- 误以为“加了 synchronized 就线程安全”,却混用静态/实例锁来保护同一份数据,会导致竞态条件
怎么选?看你要保护的数据归属
一句话判断:
- 数据是 属于整个类 的(static 字段、全局配置),就用静态同步或
synchronized(YourClass.class) - 数据是 属于某个具体对象 的(非 static 字段、对象状态),就用实例同步或
synchronized(this) - 更推荐用同步代码块 + 明确锁对象(比如 private final Object lock = new Object();),避免锁粒度粗或锁对象被意外暴露

















