分析volatile

volatile作用:

        我们看到的最多的解释volatile具备两个特性:volatile保证内存可见性、禁止指令重排

        那我们就来详细了解这两个特性:首先来了解内存可见性!

内存可见性:

      可见性:指线程之间的可见性,当多个线程访问同一个变量时,当一个线程修改了该共享变量的值新值对于其他线程来说是可以立即得知的。

      那既然volatile关键字能够保证内存可见性,那我就来个例子看看是否可以保证内存可见性:

      example1:当我们的flag变量没有用volatile修饰的时候: 

     main线程先睡眠(这里是为了让线程A读取到未修改的值),从主内存加载flag的值”0“到工作内存并修改为“1”,更新到主内存中;

     线程A从主内存加载flag的值为“0”到自己的工作内存中(因为main线程睡眠,所以这里读取的值是main线程还未修改值,这里就是Thread.sleep(1000)的作用),所以我们的线程A工作内存的flag一直为“0”,我们的while循环是一直满足条件的,所以控制台肯定是不会停止的会一直在循环! 

public class TestVolatile3 {
    //volatile
    private static  int flag = 0;
    private static int testNum = 0;
    private static int testNum2 = 0;
    public static void main(String[] args) throws Exception {
        new Thread(()->{
            while (flag == 0){
            }
        },"线程A").start(); //
        Thread.sleep(1000);
      //  testNum =1;
        /**
         * main线程修改了flag的值,并更新到主内存中,那么线程A能够读取到main线程修改后的值吗?
         * 肯定读取不到的,所以这里后台会一直在循环!后台不会停止
         */
        flag = 1; 
       // testNum2 = 1;

    }
}

    example1.1:当我们把flag变量用volatile关键字修饰,我们看结果:

对上面的结果可以证实 volatile确实具备了 可见性的特性,那我们就来看看volatile底层到底是怎么做的,怎么实现可见性的!

刨根底层实现

我们用javap 查看的时候会发现加不加volatile关键字 生成的字节码都是一样的,所以我们要查看生成的汇编语言到底是怎么样的

需要引入hsdis-amd64.dll                                         -XX:+PrintAssembly 参数输出反汇编 

在我们的jvm参数里面添加:-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:-Inline

我们运行后会发现加了volatile的汇编会多出” lock addl $0x0,(%rsp) “ 操作(这里是写的操作,该操作的作用相当于一个内存屏障Memory Barrier或Memory Fence:指重排序后不能把后面的指令重排序到内存屏障之前的位置)我们下面来看看这个操作的含义:

lock addl $0x0,(%rsp) 指令,这个指令中的“addl $0x0,(%rsp)”(把rsp的寄存器的值加0)这个是一个空操作,主要是前面的lock前缀,它的作用是将本处理器的缓存写入内存,该写入动作也会引起别的处理器或者别的内核无效化其缓存。所以通过这样一个空操作,可让前面volatile变量的修改对其他处理器立即可见。所以就实现了所谓的 "  内存可见性 “!!!!!!!

所以我们可以得出这个指令(内存屏障):这个保证了两个事情,第一,不会重排序。第二,所有的变量值都会回写到主内存中,从而在这个指令之后,变量值对其他线程可见

 

下班了 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值