真实面经题目 · 原创解析
synchronized 和 ReentrantLock 有什么区别?
synchronized 是 JVM 层面的内置锁,语法简单,自动加锁释放;ReentrantLock 是 JUC 提供的显式锁,基于 AQS,功能更丰富。两者都可重入,都能保证互斥和可见性,但在使用方式、等待能力、公平性、条件队列和可中断性上差异明显。
真实面经题目 · 原创解析
synchronized 是 JVM 层面的内置锁,语法简单,自动加锁释放;ReentrantLock 是 JUC 提供的显式锁,基于 AQS,功能更丰富。两者都可重入,都能保证互斥和可见性,但在使用方式、等待能力、公平性、条件队列和可中断性上差异明显。
可以从实现层和能力层对比。synchronized 依赖对象监视器,由 JVM 自动进入和退出,异常时也会自动释放,适合简单临界区;ReentrantLock 基于 AQS,需要手动 lock 和 unlock,通常必须在 finally 中释放。功能上,ReentrantLock 支持公平锁、非公平锁、可中断获取、限时尝试获取、多个 Condition 条件队列;synchronized 只有一个对象等待集合,不能直接设置公平性,也不能在阻塞获取锁时主动响应中断。选择时,简单互斥优先 synchronized,需要高级控制再用 ReentrantLock。
synchronized 是 Java 语言级关键字,进入和退出临界区由 JVM 根据对象监视器完成,编译后对应 monitorenter 和 monitorexit 语义。ReentrantLock 是类库层面的显式锁,底层通过 AQS 的 state、等待队列和 LockSupport 实现。两者都能提供互斥和内存可见性,但一个由 JVM 管理,一个由并发框架管理。
synchronized 的优势是简单,代码块或方法退出时会自动释放锁,即使发生异常也能保证监视器退出。ReentrantLock 必须显式调用 lock 和 unlock,工程上通常要求把 unlock 放在 finally 中,否则异常路径可能导致锁永远不释放。显式锁的使用成本更高,但也换来了更细粒度的控制能力。
ReentrantLock 的能力更丰富,可以使用 lockInterruptibly 在等待锁时响应中断,也可以使用 tryLock 立即尝试或限时尝试,适合避免死等、实现降级或超时返回。synchronized 在等待进入临界区时不能通过普通中断直接退出,只能等锁可用。这一点在需要可取消任务或严格延迟控制的场景中很关键。
synchronized 的 wait、notify、notifyAll 依赖对象监视器,每个锁对象只有一个等待集合,复杂条件下容易出现通知范围过大或条件混杂。ReentrantLock 可以创建多个 Condition,每个 Condition 对应独立条件队列,比如一个队列可以分别管理非空和非满条件。这让等待通知逻辑更清晰,也能减少无关线程被唤醒。
synchronized 不提供直接的公平性配置,锁竞争由 JVM 和调度机制决定。ReentrantLock 可以选择公平或非公平模式,非公平通常吞吐更好,公平模式能减少饥饿但成本更高。实际选择上,简单同步、低复杂度临界区优先 synchronized;需要超时、可中断、公平策略、多个条件队列或更强可观测控制时,选择 ReentrantLock。
是的。synchronized 对同一线程重复进入同一监视器是可重入的,ReentrantLock 通过 AQS 的 state 记录重入次数。
不一定。现代 JVM 对 synchronized 做了大量优化,简单场景下它通常足够好。ReentrantLock 的优势更多在功能控制,而不是绝对性能。
因为它不会自动释放锁。如果临界区抛出异常但没有执行 unlock,其他线程可能永久阻塞,形成严重故障。
wait/notify 绑定对象监视器且只有一个等待集合;Condition 绑定 Lock,一个锁可以创建多个条件队列,表达复杂条件更清晰。