java八股文面试[多线程]——Synchronized优化手段:锁膨胀、锁消除、锁粗化和自适应自旋锁
1.锁膨胀 (就是锁升级)
我们先来回顾一下锁膨胀对 synchronized 性能的影响,所谓的锁膨胀是指 synchronized 从无锁升级到偏向锁,再到轻量级锁,最后到重量级锁的过程,它叫锁膨胀也叫锁升级。

JDK 1.6 之前,synchronized 是重量级锁,也就是说 synchronized 在释放和获取锁时都会从用户态转换成内核态,而转换的效率是比较低的。但有了锁膨胀机制之后,synchronized 的状态就多了无锁、偏向锁以及轻量级锁了,这时候在进行并发操作时,大部分的场景都不需要用户态到内核态的转换了,这样就大幅的提升了 synchronized 的性能。
2.锁消除
很多人都了解 synchronized 中锁膨胀的机制,但对接下来的 3 项优化却知之甚少,这样会在面试中错失良机,那么我们本文就把这 3 项优化单独拎出来讲一下吧。
锁消除指的是在某些情况下,JVM 虚拟机如果检测不到某段代码被共享和竞争的可能性,就会将这段代码所属的同步锁消除掉,从而到底提高程序性能的目的。
锁消除的依据是逃逸分析的数据支持,如 StringBuffer 的 append() 方法,或 Vector 的 add() 方法,在很多情况下是可以进行锁消除的,比如以下这段代码:
public String method() {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append("i:" + i);
}
return sb.toString();
}
以上代码经过编译之后的字节码如下:

从上述结果可以看出,之前我们写的线程安全的加锁的 StringBuffer 对象,在生成字节码之后就被替换成了不加锁不安全的 StringBuilder 对象了,原因是 StringBuffer 的变量属于一个局部变量,并且不会从该方法中逃逸出去,所以此时我们就可以使用锁消除(不加锁)来加速程序的运行。
3.锁粗化
锁粗化是指,将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁。
我只听说锁“细化”可以提高程序的执行效率,也就是将锁的范围尽可能缩小,这样在锁竞争时,等待获取锁的线程才能更早的获取锁,从而提高程序的运行效率,但锁粗化是如何提高性能的呢?
没错,锁细化的观点在大多数情况下都是成立了,但是一系列连续加锁和解锁的操作,也会导致不必要的性能开销,从而影响程序的执行效率,比如这段代码:
public String method() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
// 伪代码:加锁操作
sb.append( + i);
// 伪代码:解锁操作
}
return sb.toString();
}
这里我们不考虑编译器优化的情况,如果在 for 循环中定义锁,那么锁的范围很小,但每次 for 循环都需要进行加锁和释放锁的操作,性能是很低的;但如果我们直接在 for 循环的外层加一把锁,那么对于同一个对象操作这段代码的性能就会提高很多,如下伪代码所示:
public String method() {
StringBuilder sb = new StringBuilder();
// 伪代码:加锁操作
for (int i = 0; i < 10; i++) {
sb.append( + i);
}
// 伪代码:解锁操作
return sb.toString();
}
锁粗化的作用:如果检测到同一个对象执行了连续的加锁和解锁的操作,则会将这一系列操作合并成一个更大的锁,从而提升程序的执行效率。
4.自适应自旋锁
自旋锁是指通过自身循环,尝试获取锁的一种方式,伪代码实现如下:
// 尝试获取锁
while(!isLock()){}
自旋锁优点在于它避免一些线程的挂起和恢复操作,因为挂起线程和恢复线程都需要从用户态转入内核态,这个过程是比较慢的,所以通过自旋的方式可以一定程度上避免线程挂起和恢复所造成的性能开销。
但是,如果长时间自旋还获取不到锁,那么也会造成一定的资源浪费,所以我们通常会给自旋设置一个固定的值来避免一直自旋的性能开销。然而对于 synchronized 关键字来说,它的自旋锁更加的“智能”,synchronized 中的自旋锁是自适应自旋锁,这就好比之前一直开的手动挡的三轮车,而经过了 JDK 1.6 的优化之后,我们的这部“车”,一下子变成自动挡的兰博基尼了。

自适应自旋锁是指,线程自旋的次数不再是固定的值,而是一个动态改变的值,这个值会根据前一次自旋获取锁的状态来决定此次自旋的次数。比如上一次通过自旋成功获取到了锁,那么这次通过自旋也有可能会获取到锁,所以这次自旋的次数就会增多一些,而如果上一次通过自旋没有成功获取到锁,那么这次自旋可能也获取不到锁,所以为了避免资源的浪费,就会少循环或者不循环,以提高程序的执行效率。简单来说,如果线程自旋成功了,则下次自旋的次数会增多,如果失败,下次自旋的次数会减少。
总结
本文我们介绍了 4 种优化 synchronized 的方案,其中锁膨胀和自适应自旋锁是 synchronized 关键字自身的优化实现,而锁消除和锁粗化是 JVM 虚拟机对 synchronized 提供的优化方案,这些优化方案最终使得 synchronized 的性能得到了大幅的提升,也让它在并发编程中占据了一席之地。
知识来源:
百度安全验证
相关文章:
java八股文面试[多线程]——Synchronized优化手段:锁膨胀、锁消除、锁粗化和自适应自旋锁
1.锁膨胀 (就是锁升级) 我们先来回顾一下锁膨胀对 synchronized 性能的影响,所谓的锁膨胀是指 synchronized 从无锁升级到偏向锁,再到轻量级锁,最后到重量级锁的过程,它叫锁膨胀也叫锁升级。 JDK 1.6 之前…...
【数据结构】队列---C语言版(详解!!!)
文章目录 🐸一、队列的概念及结构🍄1、队列的概念定义🍄2、动图演示 🐸二、队列的实现🐸三、链表结构队列详解🍎创建队列的结构⭕接口1:定义结构体(QNode、Queue)⭕接口2…...
java:详解http模块request对象
文章目录 背景继承关系获取数据request获取请求行数据获取请求头数据获取请求体数据 示例:防盗链其他功能获取请求参数通用方式请求转发共享数据获取ServletContext 背景 在 Java 中,HTTP 模块的 request 对象和 response 对象分别表示客户端向服务器发…...
力扣20. 有效的括号
20. 有效的括号 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应…...
用springboot+elasticserach7的demo,对比sider和百度ai的异同
对比aigc引擎:sider chatgpt3.5和百度ai 提示词: springboot2.5,连接elasticsearch7的demo,要有基本的操作,用模板方法 以下是一个使用Spring Boot 2.5连接Elasticsearch 7的示例代码,包括基本的操作方法…...
Python的pymysql模块与MySQL数据库的互动:基础与实例
Python的pymysql模块与MySQL数据库的互动:基础与实例 一、连接数据库二、创建游标三、执行SQL命令四、关闭连接 在Python的世界里,操作MySQL数据库最常用的库就是pymysql。 pymysql是一个灵活且易于使用的库,它允许我们以Python的方式操作MyS…...
滑动窗口实例1(长度最小的子数组)
题目: 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: …...
EI、Scopus双检索| 2023年第四届自动化、机械与设计工程国际会议
会议简介 Brief Introduction 2023年第四届自动化、机械与设计工程国际会议(SAMDE 2023) 会议时间:2023年12月8 -10日 召开地点:中国南京 大会官网:www.samde.org 机械设计制造及其自动化学科在国民经济中处于极其重要…...
【混合时变参数系统参数估计算法】使用范数总和正则化和期望最大化的混合时变参数系统参数估计算法(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
vue的公共方法封装以及class高阶封装
一、Vue.use与Vue.prototype的区别和用法 1、Vue.use和Vue.prototype区别 相同点:都是注册插件的方式,没有本质区别,都是在vue.prototype上添加了一个方法不同点:vue.use适用于注册vue生态内的插件(vuex、router、elementUI)&…...
OpenGL-入门-BMP像素图glReadPixels(1)实现读取屏幕中间的颜色和获取屏幕上鼠标点击位置的颜色
glReadPixels函数用于从帧缓冲区中读取像素数据。它可以用来获取屏幕上特定位置的像素颜色值或者获取一块区域内的像素数据。下面是该函数的基本语法: void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *da…...
斥资4亿,收购这家WLAN厂商,结果……
晚上好,我的网工朋友 不少朋友可能有隐形,2019年的时候,Juniper花费4.05亿美元,收购WiFi初创公司Mist Systems。 Mist Systems是一家买无线产品起家的公司,由前思科高管创建的。主打的产品是“AI-Driven WLAN”&…...
【简单】2511. 最多可以摧毁的敌人城堡数目
原题链接:https://leetcode.cn/problems/maximum-enemy-forts-that-can-be-captured 2511. 最多可以摧毁的敌人城堡数目 给你一个长度为 n ,下标从 0 开始的整数数组 forts ,表示一些城堡。forts[i] 可以是 -1 ,0 或者 1 &#…...
Linux用一键安装包部署禅道(18.5版本)
一、安装 禅道软件下载地址:禅道官方下载地址 - 禅道开源项目管理软件 - 禅道开源项目管理软件 请根据自己的需要下载对应的版本。 官方教程地址: (推荐)Linux用一键安装包 - 禅道使用手册 - 禅道开源项目管理软件 注:Linux 一键安装包必须直接解压到 …...
【2】openGL shader着色器分析三角形填色
源代码在下面。文档查询 > docs.gl 结果展示:使用自己的shader和打印错误描述 该篇主要在上一部分代码的基础上添加了自己写的shader,即着色器。最常用的两个着色器 vertex shader 和 fragment shader,即顶点着色器和片段着色器。 大概…...
mysql数据表Table is marked as crashed and should be repaired 的解决办法
错误原因 网上查了一下,错误的产生原因,有网友说是频繁查询和更新XXXX表造成的索引错误,还有说法是Mysql数据库因某种原因而受到了损坏。 【如:数据库服务器突发性断电,在数据表提供服务时对表的源文件进行某种操作都…...
【Unity基础】1.项目搭建与视图编辑
【Unity基础】1.项目搭建与视图编辑 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,终于要开始写基础系列的博客了,前两篇的内容基本上与入门系列相同,如果有紧跟入门系列的同学可以直接从第三篇文章开始看 好了话不多说我们开…...
C语言每日一练---Day(14)
本专栏为c语言练习专栏,适合刚刚学完c语言的初学者。本专栏每天会不定时更新,通过每天练习,进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字:统计每个月兔子的总数 数列的和 💓博主csdn个人主页&#x…...
基于孔雀算法优化的BP神经网络(预测应用) - 附代码
基于孔雀算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于孔雀算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.孔雀优化BP神经网络2.1 BP神经网络参数设置2.2 孔雀算法应用 4.测试结果:5.Matlab代码 摘要…...
【小沐学Unity3d】3ds Max 骨骼动画制作(蒙皮修改器skin)
文章目录 1、简介2、蒙皮修改器3.1 骨骼对象测试3.2 Biped对象测试 3、动画制作4、FBX导出结语 1、简介 “蒙皮”修改器是一种骨骼变形工具,主要设计用于通过另一个对象对一个对象进行变形来创建角色动画。可使用骨骼、样条线和其他对象变形网格、面片和 NURBS 对象…...
电话号码定位开源工具实战完全指南:从部署到企业应用
电话号码定位开源工具实战完全指南:从部署到企业应用 【免费下载链接】location-to-phone-number This a project to search a location of a specified phone number, and locate the map to the phone number location. 项目地址: https://gitcode.com/gh_mirro…...
5分钟快速上手:AsrTools智能语音转文字工具全攻略
5分钟快速上手:AsrTools智能语音转文字工具全攻略 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text…...
Mojo加速Python科学计算:如何在72小时内将AI推理速度提升8.6倍(附完整可运行代码)
第一章:Mojo与Python混合编程概述Mojo 是一种为 AI 系统量身打造的现代系统编程语言,兼具 Python 的易用性与 C/C 的执行效率。它原生兼容 Python 生态,允许开发者在同一个项目中无缝调用 Python 模块、复用现有 NumPy/Torch 代码,…...
揭秘Windows热键失踪案:Hotkey Detective侦探手册
揭秘Windows热键失踪案:Hotkey Detective侦探手册 【免费下载链接】hotkey-detective A small program for investigating stolen hotkeys under Windows 8 项目地址: https://gitcode.com/gh_mirrors/ho/hotkey-detective 你是否曾在Windows系统中按下熟悉的…...
Hunyuan-MT-7B-WEBUI新手必看:5分钟搞定部署,开启多语言翻译之旅
Hunyuan-MT-7B-WEBUI新手必看:5分钟搞定部署,开启多语言翻译之旅 1. 为什么选择Hunyuan-MT-7B-WEBUI 在全球化交流日益频繁的今天,语言障碍成为许多个人和团队面临的实际问题。Hunyuan-MT-7B-WEBUI作为腾讯混元开源系列中的翻译专用模型&am…...
告别布局跳动!Android Dialog+EditText+软键盘的终极适配指南(含Kotlin代码)
Android Dialog软键盘适配全攻略:从布局跳动到完美交互 在Android开发中,Dialog与软键盘的交互一直是让开发者头疼的问题。当EditText获得焦点时,弹出的软键盘经常会遮挡输入框或导致布局跳动,严重影响用户体验。本文将深入探讨Di…...
foobar2000皮肤焕新:用foobox-cn打造沉浸式音乐体验
foobar2000皮肤焕新:用foobox-cn打造沉浸式音乐体验 【免费下载链接】foobox-cn DUI 配置 for foobar2000 项目地址: https://gitcode.com/GitHub_Trending/fo/foobox-cn 作为音乐爱好者,你是否也曾因foobar2000默认界面的单调乏味而却步…...
深入解析GNSS信号跟踪环路:从PLL/DLL原理到Python仿真实践
1. GNSS信号跟踪环路基础概念 当你用手机导航时,背后其实藏着一套精密的信号追踪系统。想象一下,头顶的GPS卫星就像演唱会上的歌手,而你的手机接收机则是要听清歌词的观众。但现实中存在两个主要干扰:一是你和歌手都在移动&#x…...
抖音内容一键保存:3分钟搞定无水印批量下载完整指南
抖音内容一键保存:3分钟搞定无水印批量下载完整指南 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 你是不是也遇到过这样的烦恼?看到精彩的抖音视频想保存下来反复学习,却…...
避开这些坑,你的51单片机ADC读数才准确:XPT2046电路设计与软件滤波实战
51单片机ADC精度提升实战:XPT2046硬件优化与软件滤波全解析 当你在51单片机项目中使用XPT2046进行ADC采样时,是否遇到过这些情况:电位器调节时数值跳变剧烈、光敏电阻读数不稳定、热敏电阻测温结果漂移?这些问题往往不是代码逻辑错…...
