Java中的锁升级机制

目录

核心思想

Java对象头(Object Header)与Mark Word

锁升级的详细步骤

1. 无锁(No Lock)

2. 偏向锁(Biased Locking)

3. 轻量级锁(Lightweight Lock)

4. 重量级锁(Heavyweight Lock)

流程图

总结与意义


这是一个非常重要的概念,它主要是针对 synchronized 关键字在JVM层面的优化,目的是为了在保证线程安全的同时,尽量减少获取锁和释放锁带来的性能开销。

核心思想

锁升级的核心思想是:JVM会根据实际运行时锁的竞争情况,动态地将锁从低开销的状态升级为高开销、高保障的状态。

在Java早期版本中,synchronized 的实现非常直接,被称为“重量级锁”,性能较差。但从 HotSpot JDK 1.6 开始,JVM团队对 synchronized 进行了重大优化,引入了偏向锁轻量级锁,以及锁升级的概念,使得它的性能得到了极大的提升,现在在很多场景下已经不再比 ReentrantLock 慢很多。

Java对象头(Object Header)与Mark Word

要理解锁升级,首先要知道Java对象在内存中的布局。每个Java对象在堆内存中都有一个对象头

对象头主要包含两部分:

  1. Mark Word:存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志等。这是锁升级机制的核心。

  2. Klass Pointer:指向对象元数据的指针,JVM通过它来确定对象是哪个类的实例。

锁的状态信息就记录在 Mark Word 中。锁升级的过程,其实就是Mark Word中内容变化的过程。


锁升级的详细步骤

锁的升级路径是单向的,从低到高:无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁。这个过程是不可逆的。

1. 无锁(No Lock)
  • 状态:一个新创建的对象,还没有任何线程来竞争它。

  • Mark Word:存储对象的哈希码、分代年龄等信息。锁标志位为 01

2. 偏向锁(Biased Locking)
  • 设计初衷:在没有实际竞争只有一个线程多次使用锁的场景下,消除整个同步的开销(比如 StringBuffer 的很多方法都是 synchronized 的,但通常只会在单线程中使用)。

  • 工作原理:当第一个线程访问同步块时,JVM会将锁置为偏向模式,并在Mark Word中记录这个线程的ID。之后这个线程再次进入和退出同步块时,不需要进行任何CAS操作来加锁和解锁,只需要简单检查一下Mark Word中是否存储着自己的线程ID。

  • 升级触发条件:一旦有另一个线程来尝试获取这个锁(发生了竞争),偏向锁就会失效。

  • 锁标志位01 (同时有额外位标识是否为偏向模式)。

可以把它想象成“贴标签”:第一个线程来了,在对象上贴了个标签“此物归我所有”。以后它再来,看到自己的标签就直接用了。直到有另一个人也想来用,标签就被撕掉。

注意:由于维护偏向锁本身也有开销,且在实际多线程环境中,真正的无竞争场景并不多,从JDK 15开始,偏向锁已被默认禁用。但理解它对于理解整个锁升级体系依然至关重要。

3. 轻量级锁(Lightweight Lock)
  • 设计初衷:当锁确实存在竞争,但竞争的激烈程度很低(即线程几乎是交替执行,没有同时抢锁),避免直接使用重量级锁带来的巨大开销。

  • 工作原理

    1. 当线程要获取锁时,JVM会在当前线程的栈帧中创建一个名为锁记录(Lock Record)的空间。

    2. 将对象头的Mark Word复制到锁记录中(称为Displaced Mark Word)。

    3. 线程尝试使用CAS操作将对象头的Mark Word替换为指向该锁记录的指针。

    4. 如果CAS成功,当前线程就获得了锁,此时锁标志位变为 00

    5. 如果CAS失败(说明其他线程已经在竞争这个锁了),当前线程会尝试自旋(循环重试)来获取锁。

  • 升级触发条件:如果自旋了一定次数后(JVM有自适应策略,自旋次数不固定)还没有获得锁,或者自旋期间又有第三个线程来竞争,轻量级锁就会膨胀为重量级锁。

  • 锁标志位00

可以把它想象成“抢凳子”:大家(线程)礼貌地转着圈(自旋)等凳子(锁),谁先坐下谁就用。但如果等太久或者人太多,游戏规则就变了。

4. 重量级锁(Heavyweight Lock)
  • 设计初衷:处理高激烈度的锁竞争场景。

  • 工作原理:此时锁会向操作系统内核申请互斥量(Mutex)。未能获取到锁的线程会被挂起(进入阻塞状态),并放入一个等待队列中。当锁被释放时,操作系统会负责唤醒等待队列中的线程,让它们重新竞争锁。

  • 开销:这个过程中涉及用户态到内核态的切换、线程的挂起和唤醒,是开销最大的一种锁状态。

  • 锁标志位10

可以把它想象成“正式排队”:没拿到锁的人不再自己傻等,而是去休息室(等待队列)睡觉(阻塞),由管理员(操作系统)叫号唤醒。


流程图

下图清晰地展示了锁升级的全过程:

总结与意义

  1. 优化目的:锁升级是一种“按需付费”的优化机制。JVM会根据竞争的激烈程度,从低开销的方案开始尝试,只有在不得已时才会使用开销最大的方案。这极大地提高了 synchronized 在常见场景下的性能。

  2. 不可逆性:锁只能升级,不能降级。这是为了节省在激烈竞争环境下不必要的降级开销。

  3. 实际应用:对于开发者来说,这个过程是完全透明的,由JVM自动完成。我们只需要安心使用 synchronized 关键字,JVM会在背后为我们选择最优的锁方案。

  4. 与ReentrantLock的对比ReentrantLock 的实现更类似于“一开始就是重量级锁”的思路(虽然它也在用户态做了很多优化,如CAS自旋),但它提供了更灵活的功能(如可中断、公平锁等)。而 synchronized 的优势在于语法简洁和JVM的自动优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95576.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Scikit-learn Python机器学习 - 特征预处理 - 标准化 (Standardization):StandardScaler

锋哥原创的Scikit-learn Python机器学习视频教程: 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识,包括机器学习概述,特征工程(数据…

windows下wsl2 ubuntu开发配置

配置环境变量# 设置方式 命令/文件 生效范围 适用场景 # 临时 export FORCE_UNSAFE_CONFIGURE1 当前终端 临时编译软件 # 用户级永久 ~/.bashrc或~/.profile 当前用户 长期使用(单用户) # 系统级永久 /etc/environment或/…

网络编程 05:UDP 连接,UDP 与 TCP 的区别,实现 UDP 消息发送和接收,通过 URL 下载资源

一、概述 记录时间 [2025-09-02] 前置文章: 网络编程 01:计算机网络概述,网络的作用,网络通信的要素,以及网络通信协议与分层模型 网络编程 02:IP 地址,IP 地址的作用、分类,通过 …

告别线缆束缚!AirDroid Cast 多端投屏,让分享更自由

AirDroid Cast 是一款功能强大的跨平台投屏应用,能够轻松实现手机、电脑之间以及手机之间的屏幕共享与控制。无论是工作演示、在线教学还是游戏直播,AirDroid Cast 都能提供流畅稳定的投屏体验。 1. 下载与安装 您可以通过以下链接下载 AirDroid Cast&…

从零开始学大模型之大模型训练流程实践

大模型训练流程实践 本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型开发 学习视频/籽料/面试题 都在这>>Github<< >>Gitee<< 6.1 模型预训练 在上一章&#xff0c;我们逐步拆解了 LLM 的模型结构及训练过程&#xff0c;从零手…

一文从零部署vLLM+qwen0.5b(mac本地版,不可以实操GPU单元)

第一步&#xff1a;下载anaconda for mac https://zhuanlan.zhihu.com/p/350828057 知乎保姆级教程 https://www.anaconda.com/docs/getting-started/anaconda/install#macos-linux-installation 下载地址 第二步&#xff1a;部署vllm的虚拟环境 https://www.53ai.com/news/Op…

Go语言Range用法全解析

引言Go 语言中的 range 关键字是集合遍历的核心语法结构&#xff0c;它提供了一种高效且类型安全的方式来迭代各种数据结构。range 的设计完美体现了 Go 语言的工程哲学 - 通过最小化的语法提供最大化的功能。标准库中的许多关键组件&#xff08;如 sync.Map、bufio.Scanner 等…

mysql进阶语法(视图)

1、视图概念 是从一个或多个表中导出来的表&#xff0c;它是一种虚拟存在的表&#xff0c;表的结构和数据都依赖于基本表 应用场景&#xff1a; 多个地方用到同样的查询结果该查询结果用到复杂的select语句 视图优点&#xff1a; 简化查询语句&#xff1a;简化用户的查询操作&a…

编程范式:提升抽象能力的思维工具

这是一个编程中的核心概念&#xff0c;它代表了编写程序的一套基本风格、方法论和哲学。学习不同的编程范式&#xff0c;就像学习用不同的工具和思维方式来解决问题&#xff0c;能极大地提升你作为程序员的抽象能力和解决问题的能力。一、什么是编程范式&#xff1f;编程范式 是…

阿里云-基于通义灵码实现高效 AI 编码 | 1 | 在 Visual Studio Code 中安装和使用灵码

文章目录一、在 Visual Studio Code 中安装和使用灵码1.1 准备工作1.2 在 Visual Studio Code 安装通义灵码1.3 登录阿里云账号免费个人运维知识库&#xff0c;欢迎您的订阅&#xff1a;literator_ray.flowus.cn 一、在 Visual Studio Code 中安装和使用灵码 本安装步骤适用于…

WordPress搭建个人网站(Linux版)

WordPress搭建个人网站&#xff0c;使用Linux系统。我需要详细说明整个过程&#xff0c;包括环境准备、安装步骤、配置优化等。首先&#xff0c;用户可能对Linux不太熟悉&#xff0c;所以需要从基础开始&#xff0c;比如选择合适的Linux发行版&#xff0c;如Ubuntu或CentOS。然…

ES模块(ESM)、CommonJS(CJS)和UMD三种格式

vite的build.lib配置生成了三种格式&#xff1a;ES模块&#xff08;ESM&#xff09;、CommonJS&#xff08;CJS&#xff09;和UMD。它们的主要区别和适用场景如下&#xff1a; ES模块&#xff08;.mjs&#xff09;&#xff1a; 使用现代JavaScript的模块语法&#xff08;import…

2026届IC秋招联芸科技IC面经(完整面试题)

联芸科技2026届数字IC后端面经数字后端培训实战项目六大典型后端实现案例 首先是自我介绍。这个每家公司必备环节。这部分内容需要自己提前准备&#xff0c;避免太过紧张影响发挥。 数字IC后端经典笔试题IC秋招笔试题之时序报告解析 1&#xff09;拿到netlist和sdc后你会如何…

一维水动力模型有限体积法(四):高级实现——平衡源项、边界条件与算法总成

引言 成功实现一个稳定且精确的水动力学模型&#xff0c;关键在于妥善处理源项和边界条件。这两个环节是数值格式产生非物理振荡和误差的主要来源。本章将详细介绍“守恒-平衡”&#xff08;well-balanced&#xff09;格式的核心技术&#xff0c;以及通过“虚拟单元”实现各类物…

VAE(变分自动编码器)技术解析

VAE&#xff08;Variational Auto-Encoder, 变分自动编码器&#xff09;1、VAE的结构为什么使用重参数化&#xff1f;2、VAE的代码实现1.重构损失&#xff08;Reconstruction Loss&#xff09;2.KL散度&#xff08;Kullback-Leibler Divergence Loss&#xff09;1&#xff09;E…

嵌入式单片机---串口通信及相关通信技术

一、通信方式分类&#xff08;一&#xff09;按数据传输线路数量划分&#xff1a;串行通信与并行通信类别定义特点并行通信多个比特同时通过并行线进行传输优点&#xff1a;传输速率较高&#xff1b;缺点&#xff1a;占用大量芯片资源串行通信将数据拆分成一个个比特&#xff0…

Elasticsearch面试精讲 Day 8:聚合分析与统计查询

【Elasticsearch面试精讲 Day 8】聚合分析与统计查询 文章标签&#xff1a;Elasticsearch, 聚合查询, 统计分析, Aggregations, 面试, 大数据, 搜索引擎, 后端开发, 数据分析 文章简述&#xff1a; 本文是“Elasticsearch面试精讲”系列的第8天&#xff0c;聚焦聚合分析与统计…

HTML HTML基础(2)

1.开发者文档W3C官网&#xff1a; www.w3c.org W3School&#xff1a; www.w3school.com.cn MDN&#xff1a; developer.mozilla.org —— 推荐。2.排版标签标签名标签含义单 / 双 标签h1 ~ h6标题双p段落双div没有任何含义&#xff0c;用于整体布局双(1). h1 最好写一个&#x…

spring.profiles.active配置的作用

1. spring.profiles (或文件名中的 ?)&#xff1a;定义配置的名称这是声明一段配置属于哪个 Profile。在同一个 application.yml 中&#xff1a;使用 spring.profiles 键来为一个配置段打上标签。yamlspring:profiles: dev # 【定义】这个配置段的名称是‘dev’ server:port: …

【开题答辩全过程】以 高校教室管理系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…