Skip to content
基础

一句话答案

synchronized 是关键字自动释放锁,Lock 是接口需手动释放(finally),Lock 额外支持公平/可中断/超时/多条件。

核心要点

ObjectMonitor 的核心结构:

cpp
ObjectMonitor {
  _owner    → 指向持有锁的线程
  _count    = 0  // 重入计数
  _EntryList → 等待锁的线程队列(阻塞状态)
  _WaitSet  → 调用 wait() 后等待唤醒的线程队列
}

获锁流程:

线程尝试获锁
  → CAS 将 _owner 设为当前线程
  → 成功:_count++,进入同步块
  → 失败(已有线程持有):进入 _EntryList 阻塞等待

持锁线程调用 wait():
  → 释放锁(_owner = null,_count = 0)
  → 当前线程移入 _WaitSet

notify():
  → 将 _WaitSet 中的线程移回 _EntryList,等待重新竞争锁

释放锁:
  → _count--
  → _count = 0 时:_owner = null,唤醒 _EntryList 中的线程竞争

可重入的实现(_count 计数器):

  • 同一线程再次获取同一把锁:检查 _owner == 当前线程_count++(重入计数)
  • 每次 monitorexit(退出 synchronized 块):_count--
  • 只有 _count == 0 时才真正释放锁(_owner = null
  • 如果不支持重入,持锁线程调用自身的 synchronized 方法会立刻死锁
追问与易错

追问方向:

  • tryLock 有什么用?举个场景?
  • Condition 对比 wait/notify 优势?
  • 什么时候必须用 Lock?

易错点:

  • ❌ Lock 比 synchronized 快——JDK6 后差距很小
  • ❌ 忘记 finally 释放 Lock

💡 记忆锚点

synchronized 像酒店房卡——插卡进门、拔卡离开,全自动但只有一个等候队列。Lock 像手动密码锁——开关全靠自己(忘了 unlock 就死锁),但能设超时、能被打断、能开多个等候区(Condition),灵活换来的是责任。底层都靠 Monitor 的 owner + EntryList + WaitSet 三件套。