java中每个对象都天然关联一个jvm内置监视器,synchronized通过该监视器实现互斥锁;监视器位于对象头,含等待队列、入口队列等;synchronized(obj)或同步方法即获取对应监视器,支持可重入,并保证原子性与可见性。

Java 中 Object 类本身不提供锁,但每个 Java 对象都天然关联一个**内置监视器(monitor)**,synchronized 关键字正是通过这个监视器实现互斥锁的。本质上,不是 Object 类“实现了锁”,而是 JVM 为每个对象分配了监视器,synchronized 是访问该监视器的语法机制。
每个对象都有唯一监视器
JVM 在对象头(Object Header)中维护一个指向监视器(Monitor)结构的指针。这个监视器包含:等待队列、入口队列、持有线程标识等。无论你 new 出什么对象(包括 new Object()),它都自带这个监视器——这是 JVM 层面的基础设施,与类定义无关。
synchronized 如何绑定监视器
当使用 synchronized(obj) 或同步非静态方法时,JVM 会尝试获取 obj 关联的监视器所有权:
- 若监视器空闲,当前线程立即获得并进入临界区
- 若已被其他线程持有,当前线程被阻塞,加入该监视器的**入口队列**等待
- 持有线程退出同步块或方法时,自动释放监视器,唤醒入口队列中的一个线程
典型用法与注意事项
常见写法包括:
-
同步代码块:
synchronized(obj) { /* 临界区 */ }—— 显式指定锁对象,推荐使用私有 final 对象(如private final Object lock = new Object();),避免锁被外部干扰 -
同步实例方法:
public synchronized void method() {...}—— 等价于synchronized(this),锁的是当前实例 -
同步静态方法:
public static synchronized void method() {...}—— 锁的是该类的Class对象(如MyClass.class),属于类级别锁
注意:synchronized 是可重入锁,同一线程可多次获取同一对象的监视器;它也保证了临界区内的**原子性**和**可见性**(因释放锁前会刷新工作内存到主存)。
不能直接操作监视器,但可以感知状态
开发者无法手动创建、销毁或查询监视器,也不能调用类似 lock() / unlock() 的方法。但可通过以下方式间接体现其存在:
-
wait()/notify()/notifyAll()必须在synchronized块内调用,因为它们操作的是同一个监视器的等待队列 - 使用
jstack可看到线程堆栈中标记为- waiting on的状态,其中地址就是监视器对应的对象 ID
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











