volatile如何保证可见性?

我们都知道volatile具有可见性和有序性,但是不保证原子性。
这篇文章主要是看一下volatile如何保障可见性的。

我们知道一般我们在使用多线程的过程中,为了保持同一个变量的一致性,都会使用volatile关键字进行修饰。
那么volatile是在内存模型中起到一个什么样的作用,是怎么样保持多个线程中同一个变量的一致性呢。

我写了一个简单的例子,如果第2个线程修改了initFlag的值,我希望线程1能立刻感知到值得变化跳出死循环。这里没用volatile修饰,线程2修改了initFlag的值后,线程1还是在死循环,并没有立刻感知到initFlag值得变化,并不是我想要得结果。

然后我在initFlag前面加了volatile修饰,打印得就是我想要得结果了。这说明线程1立刻就感知到了线程2修改了initFlag得值。

那么我们来了解一下原理,这了解原理之前,我们要画一个内存模型,那样更好帮助我们理解。
首先我们要知道JMM(java内存模型)得原子操作,有8种。

如下:分别对应图中得顺序

read(读取):从主内存读取数据
load(载入):将主内存的数据写入工作内存
use(使用):从工作内存读取数据计算
assign(赋值):将计算好的值重新赋值到工作内存中
store(存储):将工作内存的值写入主内存
write(写入):将store过去的变量值赋值给主内存中的变量
lock(锁定):将主内存变量枷锁,标识未线程独占状态
unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量

我们要特别注意一下总线这个东西。cpu和主内存是两个独立得硬件,不能直接交互数据,是通过总线来交互数据得。主内存与cpu之间进行数据交互都会经过总线。

volatile关键字会开启总线得mesi缓存一致性协议。

mesi缓存一致性协议:多个CPU从主内存读取同一个数据到各自得高速缓存,当其中某个cpu修改了缓存里得数据,该数据会马上同步回主内存,其他cpu通过总线嗅探机制可以感知到数据得变化从而将自己缓存里得数据失效

流程如下:

1.线程2修改值,以后会经过总线,然后写回主内存。
2.volatile开启总线mesi缓存一致性协议,每个cpu 都会监听总线
3.当知道其他cpu修改了变量值,立刻会失效自己工作内存中得值。
4.重新去主内存取值。

但是第四步,重新去主内存取值,怎么保障读取是最新得值呢。

把Java代码反编译后,发现会在initFlag = true;这行代码之前加 LOCK

volatile缓存可见性实现原理底层实现主要是通过汇编LOCK前缀指令,它会锁定这块内存区域得缓存(缓存行锁定)并回写到主内存。
IA-32架构软件开发手册对lock指令得解释:
1.CPU会将当前处理器缓存行的数据立即写回到系统内存
2.这个写回内存得操作会引起在其他CPU里缓存了该内存地址得数据无效(MESI协议)

如下图:

线程2修改值了以后,会在store之前加锁,锁住主内存得值,这期间其他线程的等锁释放后才能访问,主内存得值修改后会释放锁,这样保障了其他线程读取到得是最新得值。这里锁得颗粒度很小,所以影响忽略不计。这就是Volatile保障可见性得基本原理。

如有不对的地方,请望指正!

volatile如何保证可见性相关推荐

  1. Java之volatile如何保证可见性和指令重排序

    1 我们先了解CPU缓存 CPU缓存为了解决CPU运算速度与内存读写速度不匹配的问题,因为CPU运算速度要比内存读写速度快得多 一次主内存的访问通常在几十到几百个时钟周期 一次L1高速缓存的读写只需要 ...

  2. 7.volatile怎么通过内存屏障保证可见性和有序性?

    volatile通过内存屏障保证可见性 小陈:老王,你上一篇抛出一个问题volatile怎么通过内存屏障保证可见性和有序性?我现在迫不及待的想知道了. 老王:嗯嗯,我们慢慢来讲,先说说volatile ...

  3. Juc12_Volatile的可见性、不保证可见性、有序性、使用、内存屏障四大指令StoreStore、StoreLoad 、LoadLoad、LoadStore

    (1). 前面我们讲过的JMM.Happen-before,JMM是规范,有个细则叫happen-before,用来保证有序性的是volatile.synchronized关键字来捍卫 (2). vo ...

  4. 两个例子详解并发编程的可见性问题和有序性问题,通过volatile保证可见性和有序性以及volatile的底层原理——缓存一致性协议MESI和内存屏障禁止指令重排

    1. 并发编程的可见性问题 2. 并发编程的有序性问题 3. 使用volatile关键字解决可见性问题 4. 可见性问题的本质--缓存不一致 因为cpu执行速度很快,但是内存执行速度相对于CPU很慢, ...

  5. volatile关键字——保证并发编程中的可见性、有序性

    文章目录 一.缓存一致性问题 二.并发编程中的三个概念 三.Java线程内存模型 1.原子性 2.可见性 3.有序性 四.深入剖析volatile关键字 1.volatile关键字的两层语义 2.vo ...

  6. volatile学习(可见性,不保证原子性,禁止指令重排(双端检索机制))

    volatile是java虚拟机提供的轻量级的同步机制: 1.保证可见性:线程之间可见性(及时通知) 2.不保证原子性 3.禁止指令重排 先了解一下jvm同步 由于JVM运行程序的实体是线程,而每个线 ...

  7. volatile是怎么保证可见性和有序性的,为什么无法保证原子性

    文章目录 1. JMM内存模型 2. 并发编程的三大特性 3. Volatile的原理分析 在了解volatile之前,先认识一下JMM内存模型和并发编程的三大特性! 1. JMM内存模型 Java内 ...

  8. java volatile线程可见_吃透Java并发:volatile是怎么保证可见性的

    前言 volatile关键字能够保证可见性和有序性,但是volatile为什么能够保证可见性和有序性?为什么volatile又不能保证原子性? 今天,我们从CPU多核缓存架构出发,结合MESI缓存一致 ...

  9. volatile保证可见性的验证

    文章目录 一.前言 二.论证过程 三.总结 一.前言     java内存模型中的可见性是指,当一个线程修改了共享变量的值后,其他线程可以立马知道这个修改后的值.在<Java并发编程:volat ...

最新文章

  1. 如果20万用户同时访问一个热点缓存,如何优化你的缓存架构?
  2. 在Xen虚拟机下修改或同步时间失败的解决方法
  3. MySQL输入密码后闪退的解决方法
  4. MySQL 配置文件优化
  5. 在写HTML和CSS时的黄金规范
  6. 10 大方法,让您的客服中心提供更出色的服务
  7. 变量定义和声明的区别~~~概念上千万不要栽跟头!!!
  8. DevOps案例研究:庖丁解牛,剖析Google持续交付之道
  9. linux python3_在Linux上安装Python 3
  10. jQuery 1.4官方文档中文版
  11. 【原创】昆虫棋离线复盘工具v1.5 更新(BoardSpace.net hive games reviewer)
  12. Java之加密(信息摘要)工具类(依赖:java.security.MessageDigest或org.apache.commons.codec.digest.DigestUtils)...
  13. ae导出html,AE导出json格式的Web动画工具 Bodymovin v5.6.1 + 使用教程
  14. 笔记本电脑怎么在桌面添加计算机,怎么在笔记本电脑上添加便签,笔记本电脑桌面便签设置密码...
  15. PAT(甲级)1148 Werewolf - Simple Version(枚举)
  16. 人在囧途之火车调研篇
  17. 阿里云自建k8s存储插件csi安装使用
  18. 【c语言】进阶篇学习笔记
  19. SqlServer遇到以零作除数错误
  20. 盘点2022热词、网络流行语!富而喜悦摆渡人走红!

热门文章

  1. 测试特制微型气泵在低温环境下的稳定性
  2. 郑州计算机平面设计大专哪个学校最好,河南哪个学校的平面设计专业好?
  3. 计算机毕业设计Java菜市场的疫情防控管理系统(源码+系统+mysql数据库+lw文档)
  4. mysql pmt函数怎么用_制作C/C++动态链接库(dll)若干注意事项
  5. 【安全硬件】Chap.2 如何破译一个CMOS门级电路;传播延迟、动态功耗、静态功耗可能泄露电路的构造以及输入密钥;非侵入式攻击 Non-Invasive Attacks
  6. 光纤测试数据软件,光纤损耗测试数据表.doc
  7. 迅为RK3588开发板单独编译Android固件
  8. 小米3怎么开通上海地铁刷卡功能
  9. 编译原理-如何使用flex和yacc工具构造一个高级计算器
  10. pe读linux硬盘分区工具_Linux分区工具:Fdisk与Parted以及GParted