0

0

Java面试之synchronized与Lock的区别

煙雲

煙雲

发布时间:2026-01-04 09:09:10

|

724人浏览过

|

来源于php中文网

原创

synchronized不能中断等待线程,因其底层monitor不响应interrupt信号;而ReentrantLock的lockInterruptibly()可响应中断并抛出InterruptedException。

java面试之synchronized与lock的区别

为什么 synchronized 不能中断等待线程

synchronized 是 JVM 层的内置锁,进入阻塞状态后线程会挂起,且无法被 Thread.interrupt() 中断。这是由底层 monitor 实现决定的——它不响应中断信号,只会一直等锁释放。

Lock 接口(如 ReentrantLock)提供了 lockInterruptibly() 方法,调用时若线程被中断,会抛出 InterruptedException 并立即退出等待队列。

  • 使用 synchronized 时,即使调用 thread.interrupt(),线程仍卡在 monitorenter 指令上,无法响应
  • ReentrantLock.lockInterruptibly() 在获取锁前会检查中断状态,适合需要超时或可取消的场景(如任务调度、RPC 调用)
  • 注意:lockInterruptibly() 不是“自动中断”,必须配合外部中断逻辑(比如另一个线程调用 interrupt()

tryLock() 和 wait/notify 不能混用

synchronized 块内可以安全使用 Object.wait() / notify(),因为它们绑定的是同一个 monitor 对象;但 Lock 不提供原生的等待/唤醒机制,必须搭配 Condition 使用。

直接在 ReentrantLock 保护的代码里调用 wait() 会抛 IllegalMonitorStateException,因为此时线程并未持有该对象的 monitor 锁。

立即学习Java免费学习笔记(深入)”;

创一AI
创一AI

AI帮你写短视频脚本

下载
  • synchronized(obj) { obj.wait(); } 合法,obj 就是 monitor
  • lock.lock(); obj.wait(); 非法,obj 和锁无关
  • 正确方式是:Condition condition = lock.newCondition(); condition.await(); condition.signal();
  • 一个 Lock 可创建多个 Condition,实现更精细的等待队列(比如读写锁中分别管理读等待和写等待)

公平性与性能差异在哪体现

synchronized 始终是非公平的,且无法配置;ReentrantLock 默认也是非公平,但构造时传 true 可启用公平模式:new ReentrantLock(true)

公平锁会按线程入队顺序分配锁,避免饥饿,但吞吐量明显下降——每次加锁都要遍历同步队列确认头节点,还可能引发频繁的线程挂起/唤醒切换。

  • 高并发争抢下,非公平锁平均性能比公平锁高 2–3 倍(JDK8 测试数据)
  • synchronized 经过 JIT 优化后,在无竞争或轻度竞争时几乎无额外开销;而 ReentrantLock 即使未争抢,也有对象创建和方法调用成本
  • 公平锁只应在明确存在饥饿风险(如定时任务线程长期拿不到锁)时启用,不是“更安全”的默认选项

锁升级失败会导致 synchronized 退化为重量级锁

JVM 对 synchronized 做了多层优化:偏向锁 → 轻量级锁 → 重量级锁。一旦发生锁竞争(比如两个线程同时进入同一把锁),偏向锁会被撤销,后续再进入就会直接走轻量级锁路径;若自旋失败(默认 10 次),就膨胀为重量级锁,线程进入操作系统 Mutex 等待。

这个过程不可逆,且撤销偏向锁需全局安全点(stop-the-world),可能造成明显停顿。

  • ReentrantLock 没有这种“锁升级”概念,始终基于 AQS 队列,行为稳定可预期
  • 可通过 JVM 参数关闭偏向锁(-XX:-UseBiasedLocking)来规避撤销开销,尤其在容器环境或短生命周期应用中
  • 注意:JDK15+ 默认禁用偏向锁,JDK17 彻底移除,所以新项目基本不用考虑这部分复杂性
public class LockVsSyncExample {
    private final Object syncObj = new Object();
    private final ReentrantLock lock = new ReentrantLock();

    public void syncMethod() {
        synchronized (syncObj) {
            // 正确:wait 必须在 synchronized 块中
            try {
                syncObj.wait(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void lockMethod() {
        lock.lock();
        try {
            // 错误:不能在这里调用 wait()
            // syncObj.wait(); // 抛 IllegalMonitorStateException

            // 正确:用 Condition
            Condition condition = lock.newCondition();
            condition.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
}
锁的语义一致性比语法糖更重要。很多人以为 ReentrantLock 就是 synchronized 的升级版,其实它们适用边界很不同:前者适合需要中断、超时、多条件等待的显式控制场景;后者在大多数简单同步需求中更轻量、更不易出错。真正容易被忽略的是——synchronized 的 monitor 本质决定了它和 JVM 内存模型、GC 安全点、逃逸分析深度耦合,而这些细节在调试死锁或性能抖动时才突然变得关键。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

827

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

732

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

732

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

396

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16924

2023.08.03

PPT动态图表制作教程大全
PPT动态图表制作教程大全

本专题整合了PPT动态图表制作相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.07

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.3万人学习

C# 教程
C# 教程

共94课时 | 6.2万人学习

Java 教程
Java 教程

共578课时 | 43.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号