对象锁的核心作用是确保同一实例的多个线程操作串行执行,从而维护该实例内部状态的一致性与完整性;它绑定具体对象实例,保障同步方法调用的原子性链路,支持wait/notify状态协作,并与类锁分离以避免过度串行化。

对象锁的核心作用,是确保同一实例的多个线程操作不会交错执行,从而守住该实例内部状态的一致性与完整性。
保护实例变量不被并发修改
当多个线程同时调用同一个对象的同步方法(如 synchronized void update()),它们竞争的是该对象自身的锁(this)。只有拿到锁的线程能进入临界区,其他线程必须等待。这直接防止了对共享实例字段(比如 private int count)的“读-改-写”过程被中断,避免出现丢失更新、计数错误等典型竞态问题。
- 例如:两个线程同时对
counter.increment()(内部含count++)执行,若无对象锁,可能都读到 5、各自加 1 后写回 6,最终结果仍是 6 而非预期的 7;加锁后,第二个线程会等第一个完成并刷新值后再读,结果正确为 7。 - 关键点在于:锁绑定的是具体对象实例,不是方法或代码本身。不同实例(
new Counter()多次)互不影响,各自维护自己的状态完整性。
保证方法间调用的原子性链路
一个对象内部的方法常存在调用依赖。比如 withdraw() 先检查余额再扣款,中间若被其他线程插入修改,就会破坏业务逻辑。对象锁让这种“检查+执行”的组合具备原子性——只要这些方法都被声明为 synchronized,它们就共用同一把锁,天然串行化。
- 即使方法 A 内部调用同步方法 B,也不会发生死锁(因为是可重入锁),且整个调用链始终处于同一锁保护下。
- 这比在每个方法里单独加锁更简洁可靠,避免因疏漏某处而破坏状态一致性。
配合 wait/notify 实现状态驱动的协作
对象锁不仅用于互斥,还关联着该对象的监视器(monitor),支持 wait()、notify() 等操作。线程可在满足特定实例状态时(如“余额不足”)主动释放锁并等待,待其他线程改变状态(如“存入资金”)后唤醒——这种基于实例当前状态的协调,本身就是维护状态完整性的高级体现。
- 例如生产者-消费者模式中,消费者在
queue.isEmpty()为 true 时wait(),生产者插入元素后notify(),所有动作都围绕queue这一实例的状态展开。 - 没有对象锁,
wait/notify就无法安全工作,状态判断与等待动作之间会出现竞态窗口。
与类锁分离,避免过度串行化
对象锁只约束针对同一实例的操作,不干扰其他实例或静态资源。这种粒度精准地划定了“谁该管谁的状态”:实例变量归对象锁管,类变量归类锁(MyClass.class)管。二者互不干扰,既保障了每个实例自身状态的独立完整性,又避免了不必要的全局阻塞。
- 比如用户服务中,
User user1 = new User(...)和User user2 = new User(...)的修改可并行进行;但对user1的两次修改必须串行,确保其姓名、邮箱等字段始终自洽。 - 若错误地用类锁保护实例操作,会导致所有用户操作排队,性能下降且逻辑失焦。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











