Java中的synchronized锁膨胀机制怎么实现
在文章实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Java中的synchronized锁膨胀机制怎么实现》,聊聊,希望可以帮助到正在努力赚钱的你。
synchronized
在 JDK 1.5 时,synchronized 需要调用监视器锁(Monitor)来实现,监视器锁本质上又是依赖于底层的操作系统的 Mutex Lock(互斥锁)实现的,互斥锁在进行释放和获取的时候,需要从用户态转换到内核态,这样就造成了很高的成本,也需要较长的执行时间,这种依赖于操作系统 Mutex Lock 实现的锁我们称之为“重量级锁”。
什么是用户态和内核态?
用户态(User Mode):当进程在执行用户自己的代码时,则称其处于用户运行态。 内核态(Kernel Mode):当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态,此时处理器处于特权级最高的内核代码中执行。

为什么分内核态和用户态?
假设没有内核态和用户态之分,程序就可以随意读写硬件资源了,比如随意读写和分配内存,这样如果程序员一不小心将不适当的内容写到了不该写的地方,很可能就会导致系统崩溃。
而有了用户态和内核态的区分之后,程序在执行某个操作时会进行一系列的验证和检验之后,确认没问题之后才可以正常的操作资源,这样就不会担心一不小心就把系统搞坏的情况了,也就是有了内核态和用户态的区分之后可以让程序更加安全的运行,但同时两种形态的切换会导致一定的性能开销。
锁膨胀
在 JDK 1.6 时,为了解决获取锁和释放锁带来的性能消耗,引入了“偏向锁”和“轻量级锁”的状态,此时 synchronized 的状态总共有以下 4 种:
无锁
偏向锁
轻量级锁
重量级锁
锁的级别按照上述先后顺序依次升级,我们把这个升级的过程称之为“锁膨胀”。

PS:到现在为止,锁的升级是单向的,也就是说只能从低到高升级(无锁 -> 偏向锁 -> 轻量锁锁 -> 重量级锁),不会出现锁降级的情况。
锁膨胀为什么能优化 synchronized 的性能?当我们了解了这些锁状态之后自然就会有答案,下面我们一起来看。
偏向锁
HotSpot 作者经过研究实践发现,在大多数情况下,锁不存在多线程竞争,总是由同一线程多次获得的,为了让线程获得锁的代价更低,于是就引进了偏向锁。
偏向锁(Biased Locking)指的是,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下会给线程加一个偏向锁。
偏向锁执行流程
当一个线程访问同步代码块并获取锁时,会在对象头的 Mark Word 里存储锁偏向的线程 ID,在线程进入和退出同步块时不再通过 CAS 操作来加锁和解锁,而是检测 Mark Word 里是否存储着指向当前线程的偏向锁,如果 Mark Word 中的线程 ID 和访问的线程 ID 一致,则可以直接进入同步块进行代码执行,如果线程 ID 不同,则使用 CAS 尝试获取锁,如果获取成功则进入同步块执行代码,否则会将锁的状态升级为轻量级锁。
偏向锁的优点
偏向锁是为了在无多线程竞争的情况下,尽量减少不必要的锁切换而设计的,因为锁的获取及释放要依赖多次 CAS 原子指令,而偏向锁只需要在置换线程 ID 的时候执行一次 CAS 原子指令即可。
Mark Word 扩展知识:内存布局
在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为以下 3 个区域:
对象头(Header)
实例数据(Instance Data)
对齐填充(Padding)
对象头中又包含了:
Mark Word(标记字段):我们的偏向锁信息就是存储在此区域的。
Klass Pointer(Class 对象指针)
对象在内存中的布局如下:

在 JDK 1.6 中默认是开启偏向锁的,可以通过“-XX:-UseBiasedLocking=false”命令来禁用偏向锁。
轻量级锁
引入轻量级锁的目的是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统 Mutex Lock(互斥锁)产生的性能消耗。如果使用 Mutex Lock 每次获取锁和释放锁的操作都会带来用户态和内核态的切换,这样系统的性能开销是很大的。
当关闭偏向锁或者多个线程竞争偏向锁时就会导致偏向锁升级为轻量级锁,轻量级锁的获取和释放都通过 CAS 完成的,其中锁获取可能会通过一定次数的自旋来完成。
注意事项
需要强调一点:轻量级锁并不是用来代替重量级锁的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用产生的性能消耗。轻量级锁所适应的场景是线程交替执行同步块的情况,如果同一时间多个线程同时访问时,就会导致轻量级锁膨胀为重量级锁。
重量级锁
synchronized 是依赖监视器 Monitor 实现方法同步或代码块同步的,代码块同步使用的是 monitorenter 和 monitorexit 指令来实现的,monitorenter 指令是在编译后插入到同步代码块的开始位置,而 monitorexit 是插入到方法结束处和异常处的,任何对象都有一个 Monitor 与之关联,当且一个 Monitor 被持有后,它将处于锁定状态。
如以下加锁代码:
public class SynchronizedToMonitorExample {
public static void main(String[] args) {
int count = 0;
synchronized (SynchronizedToMonitorExample.class) {
for (int i = 0; i < 10; i++) {
count++;
}
}
System.out.println(count);
}
}当我们将上述代码编译成字节码之后,它的内容是这样的:

从上述结果可以看出,在 main 方法的执行中多个 monitorenter 和 monitorexit 的指令,由此可知 synchronized 是依赖 Monitor 监视器锁实现的,而监视器锁又是依赖操作系统的互斥锁(Mutex Lock),互斥锁在每次获取和释放锁时,都会带来用户态和内核态的切换,这样就增加了系统的性能开销。
今天关于《Java中的synchronized锁膨胀机制怎么实现》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
如何在Windows 10系统中查看时间线记录
- 上一篇
- 如何在Windows 10系统中查看时间线记录
- 下一篇
- win7清除arp病毒操作方法
-
- 文章 · java教程 | 2天前 |
- Java 虚拟线程连接池改造的资源边界
- 236浏览 收藏
-
- 文章 · java教程 | 2天前 | Java · 虚拟线程 · java UncaughtExceptionHandler 虚拟线程 Thread.Builder.OfVirtual
- Java Thread.Builder.OfVirtual 设置线程异常处理器
- 139浏览 收藏
-
- 文章 · java教程 | 2天前 | 数据处理 · Java教程 · java windowFixed Stream Gatherer 事件窗口
- Java Stream Gatherer 组合短窗口事件的实现步骤
- 495浏览 收藏
-
- 文章 · java教程 | 3天前 | 并发 · Java · 随机数 · RandomGeneratorFactory Java随机算法 随机数并发
- Java RandomGeneratorFactory 怎么按能力选择随机算法
- 244浏览 收藏
-
- 文章 · java教程 | 3天前 |
- Java HexFormat 怎么在字节数组和十六进制文本间转换
- 361浏览 收藏
-
- 文章 · java教程 | 3天前 | 文件处理 · nio · Java教程 · java 文件比较 Files.mismatch 字节偏移
- Java Files.mismatch 怎么定位两个文件首个差异
- 342浏览 收藏
-
- 文章 · java教程 | 3天前 | Java ·
- Java Base64 流式编码怎么避免一次加载大文件
- 182浏览 收藏
-
- 文章 · java教程 | 3天前 | Java · 可观测性 ·
- Java JFR EventStream 怎么实时消费运行事件
- 145浏览 收藏
-
- 文章 · java教程 | 3天前 | Java ·
- Java Class-File API 怎么读取类文件结构
- 419浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 284次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 339次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 336次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 303次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 124次使用
-
- Java try-with-resources 多个资源关闭顺序是什么
- 2026-09-10 501浏览
-
- 矩阵主副对角线快速定位技巧
- 2026-05-31 501浏览
-
- Java多态优化流程代码与行为分发改进
- 2026-05-26 501浏览
-
- JVM 类元数据双亲委派链表深度解析
- 2026-05-21 501浏览
-
- 反射异常处理:InvocationTargetException解析与应用
- 2026-05-16 501浏览
