面试题:JVM 对锁都进行了哪些优化?

2023-12-24 07:30

本文主要是介绍面试题:JVM 对锁都进行了哪些优化?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 锁优化
  • 自旋锁和自适应自旋
  • 锁消除
  • 锁粗化
  • 逃逸分析
  • 方法逃逸
  • 线程逃逸
  • 通过逃逸分析,编译器对代码的优化


锁优化

jvm 在加锁的过程中,会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。

自旋锁和自适应自旋

现在大多的处理器都是多核处理器 ,如果在多核心处理器,有让两个或者以上的线程并行执行,我们可以让一个等待线程不放弃处理器的执行时间。设置一个等待超时时间,看线程是否能够很快的释放锁,在等等待的这段时间可以执行一个空循环,让当前线程继续占用 CPU 的时间片。这就是所谓的「自旋锁」。

JVM 中可以通过 +XX:UseSpinning来开启自旋锁,在 JDK1.6 过后默认为我们开启。由于自旋锁的使用会让锁的竞争者占用更多的处理器时间, JVM 规定了一个自旋次数的一个参数。我们可以通过 -XX:PreBlockSping来进行更改(默认10次)。

偏向锁、轻量级锁的状态转化及对象 Mark Word 的关系转换入下图所示:

图片

锁消除

锁消除是指虚拟机即时编译器在运行时检测到某段需要同步的代码不可能存在共享数据竞争而实施的一种对锁进行消除的优化策略。锁消除的主要判断依据于逃逸分析。如果判断一段代码,在堆上所有的数据都不会逃逸出去被别的线程访问到,那就把它当作栈上的数据对待,认为它们是私有的,同步加锁就无需进行。

下面是三个字符串 x, y, z 相加的例子,无论是从源代码上还是逻辑上都没有进行同步

public String concatStr(String x, String y, String z) {return  x + y + z;
}

String 是一个不可变的类,对字符的链接总是生成新的 String 对象来进行的,因此 Javac 编译器会对 String 链接进行自动优化,在 jdk5 之前字符串链接会转换为 StringBuffer;在 jdk5 之后会转换为 StringBuilder 对象连续的 append()操作,我们看看 javac 过后,反编译的结果:

public String concatStr(String x, String y, String z) {StringBuilder sb = new StringBuilder();sb.append(x);sb.append(y);sb.append(z);return  sb.toString();
}

我们再来看看 javap反编译的结果:

图片

javap反编译的结果

这里大家可能会担心 StringBuilder不是线程安全的的操作会存在线程安全的问题吗?这里的答案是不会,x + y + z操作的优化「经过逃逸分析」过后,他的动态作用域被限制在了 concatStr方法内,就是说当前实际执行的 StringBuilder 的操作在 concatStr 方法内部,「其他的外部线程无法访问」到,所以这里「虽然有锁,但是可以被安全的消除掉。所以当我们进行编译过后,这段代码就会忽略掉所有的同步措施直接执行。」

锁粗化

原则上,我们在写代码的时候,总是推荐将同步块的作用范围限制得尽可能的小–只在共享数据的实际操作作用域中才进行同步,这样也是为了使得需要同步的操作尽可能的变少,即使存在锁的竞争,等待的锁的线程也能很快的获取到锁。大多数情况下,上面的原则都是正确的,但是如果「一系列的连续操作都是对同一个对象反复加锁和解锁,甚至加锁操作时出现在循环体之中」的,那即使没有线程的竞争,频繁的进行相互操作也会导致不必需要的性能损耗

StringBuffer buffer = new StringBuffer();
/**  锁粗化 */
public void append(){buffer.append("aaa").append(" bbb").append(" ccc");
}

上面的代码每次调用 buffer.append 方法都需要加锁和解锁,如果 JVM 家册到有一串连续的对同一个对象加锁和解锁的操作,就会将其合并成一次范围更大的加锁解锁操作,即在第一个 append 方法执行的时候进行加锁,最后一个 append 方法结束后进行解锁。

逃逸分析

逃逸分析(Escape Analysis),是一种可能减少有效 Java 程序中同步负载和内存堆分配压力的跨全局函数数据流分析算法。通过逃逸分析, Java Hotspot 编译器能够分析出一个新的对象引用范围从而决定是否要将这个对象分配到堆上,「逃逸分析的基本行为就是分析对象的动态作用域。」

方法逃逸

当一个对象在方法里面被定义后,它可能被外部方法所引用,例如调用参数传递到其他方法中,这种称为方法逃逸。

线程逃逸

当一个对象可能被外部线程访问到,比如:赋值给其他线程中访问的实例变量,这种称为线程逃逸。

通过逃逸分析,编译器对代码的优化

如果能够证明一个对象不会逃逸到到方法外或线程外(其他线程方法或者线程无法通过任何方法访问该变量),或者逃逸程度比较低(只逃逸出方法而不逃逸出线程)则可以对这个对象采用不同程度的优化:

1、栈上分配(Stack Allocations)完全不会逃逸的局部变量和不会逃逸出线程的对象,采用栈上分配,对象就会跟随方法的结束自动销毁。以减少垃圾回收器的压力。

2、标量替换(Scalar Replacement)有个对象可能不需要作为一个连续的存储结果存储也能被访问到,那么对象的部分(或者全部)可以不存储在内存,而是存储在 CPU 寄存器中。

3、同步消除(Synchronization Elimination)如果一个对象发现只能在一个线程访问到,那么这个对象的操作可以考虑不同步。

这篇关于面试题:JVM 对锁都进行了哪些优化?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/531008

相关文章

Spring @Scheduled注解及工作原理

《Spring@Scheduled注解及工作原理》Spring的@Scheduled注解用于标记定时任务,无需额外库,需配置@EnableScheduling,设置fixedRate、fixedDe... 目录1.@Scheduled注解定义2.配置 @Scheduled2.1 开启定时任务支持2.2 创建

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再