本文深入解析 Java 中 synchronized 方法和同步块的锁对象原理,阐明同一实例下多个同步方法或块如何共享对象锁,并提供更安全的私有锁实践方案。
本文深入解析 java 中 synchronized 方法与同步块的锁对象原理,阐明同一实例下多个同步方法或块如何共享对象锁,并提供更安全的私有锁实践方案。
在 Java 多线程编程中,synchronized 是最基础且关键的线程同步机制。理解其底层锁行为,对避免死锁、提升并发性能至关重要。
首先明确核心原则:所有使用 synchronized 修饰的实例方法,本质上都是以当前对象(this)为锁对象的同步块。例如:
public synchronized void methodA() {
// Do Something
}
public synchronized void methodB() {
// Do Something
}等价于:
public void methodA() {
synchronized (this) {
// Do Something
}
}
public void methodB() {
synchronized (this) {
// Do Something
}
}因此,当两个线程 t1 和 t2 持有同一个 A 实例时:
立即学习“Java免费学习笔记(深入)”;
- 若 t1 正在执行 methodA(),它已获取该实例的 intrinsic lock(即 this 锁);
- 此时 t2 尝试进入 methodB(),必须等待 t1 释放 this 锁——即使两个方法逻辑完全无关,也会相互阻塞。
这一结论同样适用于显式同步块:
public void methodA() {
synchronized (this) { /* ... */ }
}
public void methodB() {
synchronized (this) { /* ... */ }
}只要锁对象是同一个(如 this),就构成串行化访问。
⚠️ 关键风险提示:将 this 作为公共锁存在严重设计缺陷。因为 this 对外部代码可见,任何第三方代码均可对同一对象执行 synchronized (obj),导致意外的锁竞争、性能瓶颈甚至死锁,且这种依赖难以追踪和维护。
✅ 推荐实践:使用私有、不可变的锁对象
class A {
private final Object lock = new Object(); // 推荐:final + Object 实例
public void methodA() {
synchronized (lock) {
// 安全隔离的临界区
}
}
public void methodB() {
synchronized (lock) {
// 与 methodA 共享同一锁,但对外完全隐藏
}
}
}? 补充说明:new Object[0] 在原答案中出现,属笔误(数组不能直接用作锁对象);正确写法应为 new Object() 或 new byte[0](后者因轻量常被用作“哑锁”,但语义不如 Object 清晰)。始终确保锁对象为 private final,杜绝外部干扰。
总结:同步方法与同步块的互斥性取决于锁对象是否相同;默认 synchronized 方法锁定 this,易引发隐蔽竞争;工程实践中应优先采用私有锁对象,实现细粒度、可维护、可预测的线程安全控制。


















