synchronized通过对象内置监视器实现互斥,锁的是对象而非代码;实例方法锁this,静态方法锁Class对象,同步块锁指定obj;锁同一对象才互斥,且支持wait/notify协作。

synchronized 通过每个 Java 对象内置的监视器(Monitor)实现互斥,本质是让多个线程竞争同一个对象的锁,从而确保临界区同一时刻只被一个线程执行。
监视器是每个对象都有的“锁开关”
每个 Java 对象在创建时,JVM 就为其关联一个监视器,锁状态、持有线程、等待队列等信息都记录在对象头(Mark Word)中。synchronized 并不锁方法或代码块本身,而是锁住指定的对象——这个对象的监视器才是真正的同步单元。
- 修饰实例方法 → 锁的是 this(当前对象实例)
- 修饰静态方法 → 锁的是 当前类的 Class 对象
- 同步代码块
synchronized(obj)→ 锁的是 obj 引用指向的对象
进入临界区要“拿钥匙”,离开自动还钥匙
线程执行到 synchronized 代码时,必须先向目标对象的监视器申请锁。成功获取后才能执行;若锁已被占用,线程进入阻塞队列等待。JVM 保证:
- 执行完 synchronized 块/方法(含正常结束或抛异常)后,自动释放锁
- 释放锁时,会强制将工作内存中修改的共享变量刷新回主内存,保障可见性
- 加锁和解锁操作对应字节码中的 monitorenter 和 monitorexit 指令
互斥生效的前提:锁的是同一个对象
只有多个线程争抢同一个对象的监视器,才会产生互斥效果。常见误区:
- 两个线程分别调用不同对象的 synchronized 实例方法 → 各自拿各自的 this 锁,不互斥
- 一个线程调用实例方法,另一个调用静态方法 → 锁对象不同(this vs Class),不互斥
- 同步块中锁的是 new Object() 或局部变量 → 每次新建对象,锁不共享,形同虚设
监视器还支持协作机制(wait/notify)
除了基础互斥,监视器还维护一个等待集(wait set)。持有锁的线程可调用 wait() 主动释放锁并进入等待;其他线程可通过 notify()/notifyAll() 唤醒等待者。这使得监视器不仅是互斥工具,也是线程间协调的基础设施。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











