synchronized修饰方法时,实例方法锁住当前对象(this),静态方法锁住当前Class对象;锁粒度影响并发性能,实例锁支持多对象并行,类锁全局互斥;二者正交,可重入,异常自动释放锁。

synchronized 修饰方法时,本质是给当前对象(非静态方法)或当前类(静态方法)加锁,影响核心在于锁的粒度、并发性能和线程安全边界。锁粒度越粗,并发度越低;越细,控制越精确但实现成本可能上升。
实例方法加synchronized:锁住当前对象(this)
每个对象实例拥有独立的锁。不同对象调用同一synchronized实例方法,互不阻塞;同一对象的多个synchronized方法调用会串行执行。
- 等价于在方法体首尾加上
synchronized(this) { ... } - 若一个对象有 A() 和 B() 两个 synchronized 方法,线程1调用 A() 未返回前,线程2无法进入该对象的 B()
- 注意:普通方法、static 方法、其他对象的 synchronized 方法不受影响
静态方法加synchronized:锁住当前Class对象
锁的是 MyClass.class,属于类级别锁。所有该类的实例共享同一把锁,粒度比实例锁更粗。
- 等价于
synchronized(MyClass.class) { ... } - 即使创建了100个对象,只要有一个线程在执行某个 synchronized static 方法,其余所有线程都无法进入该类的任意 synchronized static 方法
- 与实例方法锁完全正交:静态方法锁不影响实例方法执行,反之亦然
锁粒度对比与选型建议
选择取决于数据共享范围和并发需求:
立即学习“Java免费学习笔记(深入)”;
- 操作的是实例成员变量 → 优先用 synchronized 实例方法(或 this 锁块)
- 操作的是类共享状态(如计数器、缓存、配置)→ 考虑 synchronized static 方法(或 Class 锁块)
- 只锁部分逻辑,而非整个方法 → 改用同步代码块,明确指定锁对象,避免无谓阻塞
- 高并发场景下,粗粒度锁易成瓶颈,可考虑
ReentrantLock、分段锁(如ConcurrentHashMap)、无锁设计(CAS)等替代方案
常见误区提醒
容易忽略但影响实际行为的关键点:
- synchronized 方法无法被继承重写“自动同步”:子类重写后默认不带 synchronized,需显式添加
- 构造方法不能用 synchronized 修饰(编译报错),对象初始化本身不具备原子性保障,需自行同步关键字段赋值
- 锁不可重入?错——synchronized 是可重入锁,同一个线程可多次获取同一把锁(如 synchronized 方法内部调用另一个本对象的 synchronized 方法)
- 异常不会导致锁泄漏:无论是否抛出异常,锁都会在方法退出时自动释放










