synchronized 的核心是锁对象:实例方法锁 this,静态方法锁 Class 对象,代码块可自定义锁;所有访问同一共享资源的代码必须用同一锁对象,且锁的是对象而非方法或代码块。

用 synchronized 锁定临界区,核心就一条:明确锁对象是谁,然后让所有需要互斥访问同一份共享资源的代码,都用同一个锁对象来保护。
修饰实例方法:锁住 this 对象
当用 synchronized 修饰非静态方法时,Java 自动以当前实例(this)为锁对象。这意味着:
- 同一个对象的多个 synchronized 实例方法之间天然互斥——线程 A 正在调用
methodA(),线程 B 就无法同时进入该对象的methodB() - 不同对象实例之间的同步方法完全不干扰——
obj1.methodA()和obj2.methodA()可并发执行 - 它等价于把整个方法体包进
synchronized(this) { ... }块里
修饰静态方法:锁住 Class 对象
静态方法属于类而非实例,所以 synchronized static 方法的锁对象是当前类的 Class 对象(如 MyClass.class)。这带来:
- 无论创建多少个该类的实例,所有线程调用这个静态方法时,都竞争同一把锁
- 它和实例方法的锁(this)完全独立——一个线程持有实例锁,不影响另一个线程进入静态同步方法
- 适合保护静态变量或全局配置等类级别资源
使用同步代码块:按需指定锁对象
这是最灵活的方式,语法为 synchronized(锁对象) { ... }。关键在于选择合适的锁:
- 用
this:效果同修饰实例方法,但可只锁关键段,避免方法整体阻塞 - 用私有 final 对象(如
private final Object lock = new Object();):避免外部误用或干扰,推荐用于细粒度控制 - 用
ClassName.class:等效于静态同步方法,适用于需跨实例协调的场景 - 切忌用可能为 null 或生命周期不可控的对象(如字符串、数组、返回值)作锁,易引发死锁或失效
锁的本质与行为要点
synchronized 不是“方法锁”或“代码块锁”,而是“对象锁”。它的实际表现取决于你锁定的是哪个对象:
- 锁一旦被某个线程持有,其他线程尝试获取**同一对象**的锁(无论是通过方法还是代码块),就会阻塞等待
- 持有锁的线程可以重入——在已持锁的方法内再调用本对象其他 synchronized 方法,不会死锁
- 锁释放发生在退出同步范围时(方法结束或代码块结束),无需手动操作
- 它同时保证原子性、可见性和有序性,不只是“防止同时执行”那么简单

















