zoukankan      html  css  js  c++  java
  • 从底层原理深度剖析volatile关键字

    本篇文章从底层原理层面深度剖析volatile关键字是如何实现内存可见性的,同时引入了Java内存模型、指令重排序以及内存屏障等知识点作为原理分析的知识支撑。

    阅读本文之前,推荐大家先阅读作者之前的一篇关于happens-before的文章,这样更有助于大家对volatile关键字底层原理的理解。

    面试官为什么总是问happens-before规则,看完这篇文章你就懂了

    简述Java内存模型

    Java内存模型分为主内存和线程工作内存两大类。

    主内存:多个线程共享的内存。如下图所示,方法区和堆属于主内存区域。

    线程工作内存:每个线程独享的内存。如下图所示,虚拟机栈、本地方法栈、程序计数器属于线程独享的工作内存。

    Java内存模型规定:所有变量都需要存储在主内存中,线程工作内存保存了变量在主内存中的副本,线程对变量的所有操作都在工作内存中进行,执行结束后在同步到主内存中去。这里必然会存在时间差,在这个时间差内,该线程对副本的操作,对于其他线程是不见的,从而造成了可见性问题。

    指令重排序

    JVM对代码进行编译优化,导致代码可能并不是按照代码编写顺序执行,而是按照JVM进行编译优化后的顺序执行。指令重排序对并发编程安全性有很大影响,所以提供了一些happens-before规则定义一些禁止编译优化的场景。

    volatile的作用

    保证共享变量的可见性:使用volatile修饰的变量,任何线程对其进行操作都是在主内存中进行的,不会产生副本,从而保证共享变量的可见性。

    防止局部指令重排序:happens-before规则中的volatile变量规则规定了一个线程先去写一个volatile变量,然后一个线程去读这个变量,那么这个写操作的结果一定对读的这个线程可见。

    volatile如何防止指令重排序

    volatile是通过内存屏障来防止指令重排序的。

    硬件层面的内存屏障分为Load Barrier 和 Store Barrier即读屏障和写屏障。

    对于Load Barrier来说,在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据。对于Store Barrier来说,在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,让其他线程可见。Java内存屏障类型把上述两种内存屏障两两组合,如下图所示:

    volatile防止指令重排序具体步骤:

    1.在每个volatile写操作的前面插入一个StoreStore屏障。

    2.在每个volatile写操作的后面插入一个StoreLoad屏障。

    3.在每个volatile读操作的后面插入一个LoadLoad屏障。

    4.在每个volatile读操作的后面插入一个LoadStore屏障。

    volatile写内存屏障示意图 

     volatile读内存屏障示意图

    volatile总结

    volatile解决的是多线程共享变量可见性问题,但是被volatile修饰的变量操作并非具有原子性。如下面代码所示:

    上述代码两个线程同时执行count++操作1000次,多次执行结果均不为2000,可见被volatile修饰的变量操作不具有原子性。注:可以通过对count++加锁的方式或使用AtomicLong和LongAdder(JDK8推荐使用)类来实现count++的原子性。

    zz:https://baijiahao.baidu.com/s?id=1655055831382625926&wfr=spider&for=pc

  • 相关阅读:
    .net core 支付宝,微信支付 一
    .net core AES加密解密及RSA 签名验签
    .net core 使用webservice
    .net core 使用X509 私钥加密请求
    .net core mysql entity映射时字符串被截断
    VS 2017 RC .net core ef+ MySql 出现错误
    IdentityServer4 简单使用,包括api访问控制,openid的授权登录,js访问
    iOS面试题之内存管理
    iOS之tableView性能优化/tableView滑动卡顿?
    iOS面试题之runloop
  • 原文地址:https://www.cnblogs.com/erichi101/p/13159194.html
Copyright © 2011-2022 走看看