真实面经题目 · 原创解析

synchronized 和 ReentrantLock 有什么区别?

synchronized 是 JVM 层面的内置锁,语法简单,自动加锁释放;ReentrantLock 是 JUC 提供的显式锁,基于 AQS,功能更丰富。两者都可重入,都能保证互斥和可见性,但在使用方式、等待能力、公平性、条件队列和可中断性上差异明显。

出现于:字节跳动 · 后端开发

60 秒回答模板

可以从实现层和能力层对比。synchronized 依赖对象监视器,由 JVM 自动进入和退出,异常时也会自动释放,适合简单临界区;ReentrantLock 基于 AQS,需要手动 lock 和 unlock,通常必须在 finally 中释放。功能上,ReentrantLock 支持公平锁、非公平锁、可中断获取、限时尝试获取、多个 Condition 条件队列;synchronized 只有一个对象等待集合,不能直接设置公平性,也不能在阻塞获取锁时主动响应中断。选择时,简单互斥优先 synchronized,需要高级控制再用 ReentrantLock。

考点 管理层级
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

实现机制

synchronized 是 Java 语言级关键字,进入和退出临界区由 JVM 根据对象监视器完成,编译后对应 monitorenter 和 monitorexit 语义。ReentrantLock 是类库层面的显式锁,底层通过 AQS 的 state、等待队列和 LockSupport 实现。两者都能提供互斥和内存可见性,但一个由 JVM 管理,一个由并发框架管理。

02

使用方式

synchronized 的优势是简单,代码块或方法退出时会自动释放锁,即使发生异常也能保证监视器退出。ReentrantLock 必须显式调用 lock 和 unlock,工程上通常要求把 unlock 放在 finally 中,否则异常路径可能导致锁永远不释放。显式锁的使用成本更高,但也换来了更细粒度的控制能力。

03

等待能力

ReentrantLock 的能力更丰富,可以使用 lockInterruptibly 在等待锁时响应中断,也可以使用 tryLock 立即尝试或限时尝试,适合避免死等、实现降级或超时返回。synchronized 在等待进入临界区时不能通过普通中断直接退出,只能等锁可用。这一点在需要可取消任务或严格延迟控制的场景中很关键。

04

条件队列

synchronized 的 wait、notify、notifyAll 依赖对象监视器,每个锁对象只有一个等待集合,复杂条件下容易出现通知范围过大或条件混杂。ReentrantLock 可以创建多个 Condition,每个 Condition 对应独立条件队列,比如一个队列可以分别管理非空和非满条件。这让等待通知逻辑更清晰,也能减少无关线程被唤醒。

05

公平性与选择

synchronized 不提供直接的公平性配置,锁竞争由 JVM 和调度机制决定。ReentrantLock 可以选择公平或非公平模式,非公平通常吞吐更好,公平模式能减少饥饿但成本更高。实际选择上,简单同步、低复杂度临界区优先 synchronized;需要超时、可中断、公平策略、多个条件队列或更强可观测控制时,选择 ReentrantLock。

易错点

  • 简单地说 ReentrantLock 性能一定更高,忽略现代 JVM 对 synchronized 的优化。
  • 只比较语法形式,没有讲到可中断、超时、公平性和多个 Condition 这些关键能力差异。
  • 使用 ReentrantLock 时忘记 finally 解锁,把显式锁写成可能永久占用的危险代码。
  • 把 synchronized 的 wait/notify 和 ReentrantLock 的 Condition 混为一谈,忽略条件队列数量和绑定对象不同。

面试官追问

两者都是可重入的吗?

是的。synchronized 对同一线程重复进入同一监视器是可重入的,ReentrantLock 通过 AQS 的 state 记录重入次数。

ReentrantLock 一定比 synchronized 性能好吗?

不一定。现代 JVM 对 synchronized 做了大量优化,简单场景下它通常足够好。ReentrantLock 的优势更多在功能控制,而不是绝对性能。

为什么 ReentrantLock 要在 finally 中释放?

因为它不会自动释放锁。如果临界区抛出异常但没有执行 unlock,其他线程可能永久阻塞,形成严重故障。

wait/notify 和 Condition 的主要区别是什么?

wait/notify 绑定对象监视器且只有一个等待集合;Condition 绑定 Lock,一个锁可以创建多个条件队列,表达复杂条件更清晰。