Java中的volatile实现原理

一、概述

1、特性(内存语义)

当一个变量被声明为 volatile 时,它具备以下两个关键特性:

  1. 可见性

    • volatile 保证了一个线程对该变量的修改,能被其他线程立即看到。也就是说,当一个线程更新了 volatile 变量的值,其他线程可以立即感知到这个变化。
    • 普通变量则不同,线程对其修改后,其他线程无法立即看到,通常需要通过主内存的同步(例如,线程A修改变量后写入主内存,线程B从主内存中读取)才能使更新对其他线程可见。
  2. 禁止指令重排序

    • volatile 禁止了编译器和处理器对该变量相关操作的指令重排序优化。这意味着,volatile 变量的读写操作在程序代码中出现的顺序,与实际执行的顺序是一致的。
    • 对于普通变量,编译器或处理器可能会为了优化性能而改变指令的顺序,这种重排序不会影响单线程的执行结果,但在多线程环境中可能导致意外行为。而 volatile 则通过内存屏障确保指令的执行顺序符合预期。
    • 这种行为符合 Java 内存模型中描述的“线程内表现为串行的语义”(Within-Thread As-If-Serial Semantics),即尽管可能存在指令重排序优化,但在单个线程内,代码的执行结果看起来是按照程序的顺序依次执行的。

volatile在Java语言规范中规定的是

Java内存模型中规定了volatile的happen-before效果,对volatile变量的写操作happen-before于后续的读。这样volatile变量能够确保一个线程的修改对其他线程可见。volatile因为不能保证原子性,所以不能在有约束或后验条件的场景下使用,如i++,常用的场景是stop变量保证系统停止对其他线程可见,double-check lock单例中防止重排序来保证安全发布等。

二、volatile 底层原理(x86架构)

1、说明

volatile关键字修饰的变量可以保证可见性与有序性,无法保证原子性。那么volatile关键字的底层原理是什么呢?我们可以通过查看Java代码的汇编指令去看一下volatile的底层原理。

我们先编写一段使用了 volatile 的代码,并通过循环多次执行该代码,以触发 JITJust-In-Time 编译器)将其编译为机器码。随后,我们可以使用 HSDIS 工具将生成的机器码反汇编为汇编代码,并对这些汇编代码进行分析,探究 volatile 的底层工作机制。

2、HSDIS 工具

(1)说明

HSDISHotSpot Disassembler)工具可以将 Java 程序在运行时生成的机器码反汇编为更容易理解的汇编代码。这对于分析 JVM 内部指令执行情况尤其有用。

如果jdk版本小于等于8还要在jdk里面添加HSDIS插件。

(2)下载地址

HSDIS 下载链接

(3)使用方法

  1. 将下载的 HSDIS 库文件(hsdis-amd64.dll,hsdis-i386.dll)放置在 Java 安装路径下的 jre/bin/serverjre/bin/client 目录中。

  2. 在运行 Java 程序时,使用 JVM 参数 -XX:+UnlockDiagnosticVMOptions-XX:+PrintAssembly 来启用 HSDIS。

以下是 HSDIS 工具启用后的效果图:
在这里插入图片描述

(4)参考

使用JVM的HSDIS插件
https://blog.csdn.net/VimGuy/article/details/81879210

在64位Windows上编译hsdis(提供下载)
https://blog.csdn.net/yizishou/article/details/53423409

3、示例代码

下面的代码中,volatile 变量 i 被多次递增。通过大量循环执行该代码,可以触发 JIT 编译器对其进行优化编译。

public class HelloVolatile {
   
    public static volatile int i = 0;
    public static void main(String[] args) {
   
        for (int j = 0; j < 100000; j++) {
   
            n();
        }
    }
    public static void n() {
   
        i++;
    }
}

另外,我们也可以使用以下 JVM 参数,这样无需多次循环即可强制 JIT 编译:

-XX:+</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值