volatile的扩展分析(1)———分析JIT编译器优化

简介: volatile的扩展分析(1)———分析JIT编译器优化

前言

提示:最近在写volatile的时候,涉及到了编译器优化的部分内容,写在voaltile里内容有点臃肿,单独写一篇博客来聊聊好了,直接先上一段代码:

public class VolatileClass {
    private static boolean isRunning = true;
    private static int i = 0;
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (isRunning) {
                i++;
            }
        });
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isRunning = false;
        System.out.println("isRunning has been changed to false");
    }
}

一、JIT 即时编译器的分类

我们知道,HotSpot集成了两个JIT compiler — C1及C2(或称为Client及Server)

两者的区别在于,前者没有应用激进的优化技术,因为这些优化往往伴随着耗时较长的代码分析。因此,C1的编译速度较快,而C2所编译的方法运行速度较快。

这两个JIT compiler(C1与C2)以及interpreter(解释器)将HotSpot的执行方式划分为五个级别:


level 0:interpreter解释执行

level 1:C1编译,无profiling(性能监控功能)

level 2:C1编译,仅方法及循环back-edge执行次数的profiling((性能监控功能))

level 3:C1编译,除level2中的profiling外还包括branch(针对分支跳转字节码)及receivertype(针对成员方法调用或类检测,如checkcast,instnaceof,aastore字节码)的profiling

level 4:C2编译

二、优化结果查看

1. 无volatile C2-level4级

7c5570fa6e6a4c68a57d152749e82020.png

可以看到jmp L0000 回跳到了inc 指令,也就是我们代码里的i++。换句话说,第一次进入循环会读我们的isRuning变量,读入寄存器后,做一个判断,但是也仅有一次判断。后续直接把循环判断的判断给去掉了,直接变成无限执行循环体了


2. 有volatile C2-level4级

我们对isRuning加了volatile,然后再运行看看情况

3b352695a22c48b3b1e9dc957c9c0da4.png

可以看到对isRuning加了volatile之后,编译器编译后的结果发生了改变,每次进行循环之前,会对isRuning再做一遍取值,如果不为0,则跳转到L0000,即满足条件再执行循环体的内容


目录
相关文章
|
SQL 机器学习/深度学习 Java
用Python进行实时计算——PyFlink快速入门
Flink 1.9.0及更高版本支持Python,也就是PyFlink。 在最新版本的Flink 1.10中,PyFlink支持Python用户定义的函数,使您能够在Table API和SQL中注册和使用这些函数。但是,听完所有这些后,您可能仍然想知道PyFlink的架构到底是什么?作为PyFlink的快速指南,本文将回答这些问题。
2802 0
用Python进行实时计算——PyFlink快速入门
|
8月前
|
人工智能 Java 决策智能
Java版Manus实现来了,Spring AI Alibaba发布开源OpenManus实现
此次官方发布的 Spring AI Alibaba OpenManus 实现,包含完整的多智能体任务规划、思考与执行流程,可以让开发者体验 Java 版本的多智能体效果。它能够根据用户的问题进行分析,操作浏览器,执行代码等来完成复杂任务等。
1503 57
|
数据库 数据安全/隐私保护 Windows
Windows远程桌面出现CredSSP加密数据修正问题解决方案
【10月更文挑战第30天】本文介绍了两种解决Windows系统凭据分配问题的方法。方案一是通过组策略编辑器(gpedit.msc)启用“加密数据库修正”并将其保护级别设为“易受攻击”。方案二是通过注册表编辑器(regedit)在指定路径下创建或修改名为“AllowEncryptionOracle”的DWORD值,并将其数值设为2。
9906 3
|
网络协议 Linux
Cannot assign requested address解决办法
Cannot assign requested address解决办法
|
存储 缓存 安全
java顶级内功心法(1) —— 可见性、MESI、volatile精讲 (8000字由浅入深)(1)
java顶级内功心法(1) —— 可见性、MESI、volatile精讲 (8000字由浅入深)
472 0
|
存储 缓存 Java
volatile的扩展分析(2)——happens-before 与 内存屏障
volatile的扩展分析(2)——happens-before 与 内存屏障
680 0
volatile的扩展分析(2)——happens-before 与 内存屏障
|
存储 缓存 Java
SpringBean生成流程详解 —— 由浅入深(附超精细流程图)
SpringBean生成流程详解 —— 由浅入深(附超精细流程图)
843 0
|
自然语言处理 JavaScript Java
【实测】如何用python3来做压力测试引擎?
【实测】如何用python3来做压力测试引擎?
|
程序员
777.【技术】解决报错:“ZIP不支持1980年以前的时间戳”
777.【技术】解决报错:“ZIP不支持1980年以前的时间戳”
420 0
|
存储 缓存 Java
java顶级内功心法(1) —— 可见性、MESI、volatile精讲 (8000字由浅入深)(2)
java顶级内功心法(1) —— 可见性、MESI、volatile精讲 (8000字由浅入深)
435 0
java顶级内功心法(1) —— 可见性、MESI、volatile精讲 (8000字由浅入深)(2)