Java中synchronized(this)与synchronized(X.class)的区别

作者:技术拾光时间:2026-06-18 08:09:07浏览:132

synchronized(this)锁定当前实例对象,不同实例互不干扰,适用于实例级同步;synchronized(X.class)锁定类的Class对象,所有实例共享同一全局锁,用于保护类级别资源。前者是实例锁,后者是类锁,作用范围不同。

很多Java开发者刚接触并发编程时,常常会被synchronized(this)和synchronized(X.class)这两个写法弄混淆——它们到底有什么区别?简单来说,一个是锁对象实例,一个是锁整个类模板。锁的粒度和作用范围完全不同,用错了轻则性能下降,重则出现诡异的并发BUG。

Java中synchronized(this)与synchronized(X.class)的区别

核心区别一句话就能说清:synchronized(this) 锁的是当前实例对象,不同实例之间互不干扰;而 synchronized(X.class) 锁的是 X 类对应的 Class 对象——这是一把全局锁,所有实例共享同一把。

synchronized(this) 是对象锁

它锁住的是调用该代码块的那个具体对象实例。每个对象在JVM内部都有自己独立的monitor(内置锁),所以两个不同的实例之间完全不影响。

  • 两个线程分别操作不同的对象实例(比如 new X() 和 new X()),它们的 synchronized(this) 互不阻塞,可以并发执行
  • 同一个对象的多个 synchronized(this) 块、或者 synchronized 修饰的非静态方法,会竞争同一把锁
  • 典型场景:保护该对象内部的状态变量,比如账户余额、计数器等仅属于当前实例的数据

synchronized(X.class) 是类锁

它锁住的是 X.class 这个 Class 类型的唯一对象。JVM 中每个类只加载一份 Class 对象,所以这把锁对所有该类的实例都生效——无论你创建了多少个实例,只要进来就得排队。

  • 无论多少个 X 实例,只要执行 synchronized(X.class) 就要排队等待同一把锁
  • 等价于 synchronized static 方法,二者共享同一把类锁
  • 适合控制类级别的资源,比如单例初始化、静态配置加载、全局计数器等

关键对比点

假设类 X 有两个实例 x1 和 x2,我们来看几种组合的情况:

  • x1.methodA() 和 x2.methodA() 都含 synchronized(this) → 不互斥,可并发执行
  • x1.methodB() 和 x2.methodB() 都含 synchronized(X.class) → 互斥,只能串行执行
  • x1 的 synchronized(this) 和 x1 的 synchronized(X.class) → 不冲突,因为锁对象不同(一个是 x1,一个是 X.class)

注意事项

实际编码中有一个容易踩的坑:避免误用 String 或常量作为锁对象,比如 synchronized("abc"),因为字符串常量池的特性可能让你的代码在看似无关的地方意外共享同一把锁。更稳妥的做法是优先使用私有 final 对象,或者直接使用 this 和 X.class 来明确语义——锁住什么、保护什么,一目了然。