每日一道面试题 10:synchronized 与 ReentrantLock 的核心区别及生产环境如何选型?

一、核心区别(面试必背,6 大维度清晰对比)

1. 底层实现

  • synchronized :JVM 层面实现,基于 Monitor 监视器锁,是 Java 内置关键字,由 JVM 自动加锁、释放锁。

  • ReentrantLock :JDK 层面实现,基于 AQS 队列同步器 ,是 java.util.concurrent.locks 包下的 API 类,需手动 lock() / unlock()

2. 可重入性

两者均支持可重入(同一个线程可重复获取锁,避免死锁)。

3. 锁获取与释放方式

  • synchronized :自动加锁,代码块执行完毕 / 抛出异常后自动释放锁,无需手动操作。
  • ReentrantLock :必须手动 lock() 加锁,unlock() 释放锁,且必须在 finally 中释放,否则极易死锁。

4. 公平锁支持

  • synchronized只支持非公平锁,线程竞争锁时随机抢占,无法保证顺序。
  • ReentrantLock :支持公平锁 & 非公平锁 ,构造方法传入 true 即为公平锁(按等待顺序获取锁)。

5. 高级特性

  • synchronized:无额外特性,仅支持基础互斥锁。
  • ReentrantLock :支持 限时等待锁可中断锁多个 Condition 条件队列,适合复杂同步场景。

6. 性能表现

  • JDK 1.6 以前:synchronized 性能远低于 ReentrantLock。
  • JDK 1.6 及以后:synchronized 引入偏向锁、轻量级锁、锁升级机制,高并发场景下性能与 ReentrantLock 接近

二、核心 API 与使用示例

1. synchronized 示例

java 复制代码
// 同步方法
public synchronized void method() {
    // 临界区代码
}

// 同步代码块
public void method() {
    synchronized (this) {
        // 临界区代码
    }
}

2. ReentrantLock 示例

java 复制代码
private Lock lock = new ReentrantLock();

public void method() {
    lock.lock();
    try {
        // 临界区代码
    } finally {
        // 必须在finally释放,避免异常导致锁泄露
        lock.unlock();
    }
}

三、适用场景

1.优先使用 synchronized

  1. 简单同步场景,代码简洁、无需手动释放锁,避免人为失误
  2. 无需公平锁、条件等待等高级特性。
  3. 追求代码简洁、减少样板代码。

2.优先使用 ReentrantLock

  1. 需要公平锁,保证线程按顺序获取锁。
  2. 需要限时获取锁tryLock(long timeout, TimeUnit unit)),避免无限阻塞。
  3. 需要可中断锁lockInterruptibly()),防止线程长时间卡死。
  4. 需要多个 Condition 条件队列,实现精准线程唤醒(如生产者消费者模式)。

四、面试高频追问

追问 1:什么是可重入锁?为什么要设计成可重入?

  • 可重入锁:同一个线程可多次获取同一把锁,不会自己锁死自己。
  • 目的:避免递归调用、多层嵌套同步代码时出现死锁。

追问 2:ReentrantLock 为什么必须在 finally 里 unlock?

  • 若临界区代码抛出异常,锁无法释放,会导致锁泄露,其他线程永久阻塞。

追问 3:synchronized 锁升级过程是什么?

无锁 → 偏向锁 → 轻量级锁 → 重量级锁竞争少时用轻量级锁(自旋),竞争激烈升级为重量级锁(阻塞)。

追问 4:Condition 相比于 synchronized 的 wait/notify 有什么优势?

  • synchronized 只有一个等待队列,唤醒时随机或全部唤醒。
  • ReentrantLock 可创建多个 Condition,实现分组等待、精准唤醒,避免无效唤醒,性能更高。

五、总结

synchronized 是 JVM 内置关键字,自动加解锁、使用简单;ReentrantLock 是 JDK API,支持公平锁、限时等待、多条件队列等高级特性。简单场景用 synchronized,复杂同步场景选 ReentrantLock。

相关推荐
一嘴一个橘子42 分钟前
springmvc 全局异常处理【补充】
java
Wang's Blog1 小时前
Vibe Coding一人即团队系列35: 基于Claude Code的Spring Boot项目初始化实践
java·spring boot·后端
Dovis(誓平步青云)1 小时前
拍视频前先把镜头想清楚:做一个分镜取景辅助器
android·java·服务器·javascript·人工智能
AI人工智能+电脑小能手1 小时前
大白话说Java设计模式-45-解释器模式(源码剖析篇)
java·设计模式·解释器模式·源码分析·pattern·spel·javacc
吴声子夜歌1 小时前
Java——开发中通用的方法和准则(二)
java·开发语言·php
袁震2 小时前
HarmonyOS 应用包体积优化与上架自检实战:从 76.2MB 到 3.6MB
java·华为·性能优化·harmonyos
zcmodeltech2 小时前
反应装置模型控制系统设计与实现:多设备协同联动方案
java·网络·数据库·stm32·嵌入式硬件·能源·制造
码视野2 小时前
基于 Spring Boot + Vue3 的【城市地下燃气管网微泄漏感知与相邻地下空间燃爆预警中台】设计与实现(含PRD/三端高保真源码/大屏)
java·前端·人工智能·spring boot·后端
2601_962071572 小时前
数据库系统架构与DBMS功能探微:现代信息时代数据管理的关键
java·开发语言·数据库
梦想的旅途22 小时前
如何高效调用企业微信通讯录API管理组织架构
java·开发语言·企业微信