synchronized通过对象级Monitor实现线程互斥,关键取决于多线程是否竞争同一锁对象:实例方法锁this、静态方法锁Class、同步块锁指定对象;JVM用monitorenter/monitorexit指令保障锁获取与释放,Monitor信息存于对象头中。

synchronized 通过对象级的监视器(Monitor)机制实现线程互斥访问。每个 Java 对象都关联一个 Monitor,线程必须先获取该 Monitor 才能进入被 synchronized 修饰的代码区域;未获取到的线程会被阻塞在入口处,直到 Monitor 可用。
锁的对象决定互斥范围
互斥是否生效,关键看多个线程是否竞争**同一个锁对象**:
- 修饰实例方法 → 锁是当前实例(this),不同对象实例之间不互斥
- 修饰静态方法 → 锁是当前类的 Class 对象,所有该类实例共享同一把锁
- 修饰同步代码块 → 锁是括号中指定的对象,需确保多线程使用的是**同一个对象引用**
JVM 层面的指令保障
编译后,synchronized 会由 JVM 在字节码中插入配对的指令:
- 进入同步区域前执行 monitorenter:尝试获取 Monitor,失败则挂起线程
- 退出同步区域(正常结束或异常)时执行 monitorexit:自动释放 Monitor
- 即使代码抛出异常,JVM 也保证 monitorexit 执行,避免死锁
Monitor 存储在对象头中
每个对象的对象头(Object Header)里保存着 Monitor 的状态信息,包括:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 持有锁的线程 ID
- 等待队列(EntryList):争抢锁失败而阻塞的线程
- 等待集合(WaitSet):调用 wait() 后挂起的线程
这种设计让锁与对象生命周期自然绑定,无需额外管理。
注意非互斥的常见情况
以下情形看似用了 synchronized,实际无法互斥:
- 两个线程分别操作 不同实例 的 synchronized 实例方法
- 一个线程调用实例方法,另一个调用 static 方法——锁对象不同(this vs Class)
- 同步代码块中锁对象每次 new 一个新对象,导致锁不一致
互斥的前提始终是:多线程访问临界区时,争夺的是同一个 Monitor。

















