volatile作用与处理器嗅探的简解
先贴一下 volatile 的作用定义
如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的
首先问题就来了,一个共享变量再被volatile修饰过后,怎么被确保所有线程看到的这个变量的值是一致的的呢,也就是说volatile是如何来保证可见性的呢?
在X86处理器下通过工具获取JIT编译器生成的汇编指令来查看对volatile进行写操作时,CPU会做什么事情。
private volatile instance = new Singleton();
转变成汇编代码,如下。
0x01a3de1d: movb $0×0,0×1104800(%esi); 0x01a3de24: lock addl $0×0,(%esp);
有 volatile 变量修饰的共享变量进行写操作的时候会多出第二行汇编代码,通过查IA-32架构软件开发者手册可知,Lock前缀的指令在多核处理器下会引发了两件事情。
1)将当前处理器缓存行的数据写回到系统内存。
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。
第一件事很容易理解,处理器在修改数据后通常都是先写入到缓存中,但是并不会第一时间写回到主内存中。
被 volatile 修饰后,这个变量被操作后会立即被写回到主内存中。(当然整个过程会比较复杂,但是我们只需要从结果上来看和简化理解就OK了。)
那第二件事中这个写回内存的操作是如何使其他CPU里缓存了该内存地址的数据无效的呢?
为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,但操作完不知道何时会写到内存。
如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。
但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。
所以,在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,
当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。
这么看来的话,各处理器之间是通过实现缓存一致性协议来完成第二件事的。
那么“每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了”,这里的处理器是如何嗅探的呢?
我百度了半天也没有单独将如何嗅探的,但是看了一遍博文后(并发研究之CPU缓存一致性协议(MESI)) ,我有了一些自己的理解,当然也只是为了简化复杂流程的简化理解。
以上是目前流行的多级缓存结构简化图,
处理器无论是想要加载数据或者写回数据,都需要通过总线(图中的②bus)来传播,
那么我们也就可以将 “处理器通过嗅探在总线上传播的数据” 这样的操作形象的理解为处理器监听 总线 上的所有修改操作,
当处理器发现自己的缓存中的某个数据在总线上被其他的处理器修改了,那么就将自己缓存中的这个数据的状态变成无效状态,
然后当处理器在处理这个无效状态的数据时,会重新去主内存中加载这个数据,然后在进行相应的操作。
比如:CPU A的cache a 已经缓存了 x,然后 CPU B的cache b 也已经缓存了 x,这时 CPU A要修改 x 的值,
然后先将修改后的数据写回到主内存中,在写回到主内存的同时被CPU B嗅探到了,并且发现这个数据在自己的cache b中也存在,然后CPU B就先将自己cache b中的 x 的状态设置成无效,
当CPU B处理到 x 时,发现 x 的状态是无效的,就只能先去主内存中重新加载 x 的值后再操作。
以上便是个人对于处理器嗅探操作的简化理解,虽然简化理解后的流程顺序和原本的流程顺序有所出入,但是这样简化理解只是为了方便自己理解和记忆。
需要了解具体的整体操作流程的话,可以去看上面提到的那边博文。
volatile作用与处理器嗅探的简解的更多相关文章
- python ConfigParser、shutil、subprocess、ElementTree模块简解
ConfigParser 模块 一.ConfigParser简介ConfigParser 是用来读取配置文件的包.配置文件的格式如下:中括号“[ ]”内包含的为section.section 下面为类 ...
- Jmeter(十八) - 从入门到精通 - JMeter后置处理器 -下篇(详解教程)
1.简介 后置处理器是在发出“取样器请求”之后执行一些操作.取样器用来模拟用户请求,有时候服务器的响应数据在后续请求中需要用到,我们的势必要对这些响应数据进行处理,后置处理器就是来完成这项工作的.例如 ...
- UE4 RHI与Render模块简解
UE4中的RHI指的是Render hardware interface,作用像Ogre里的RenderSystem,针对Dx11,Dx12,Opengl等等平台抽象出相同的接口,我们能方便能使用相同 ...
- zabbix基本监控各指标简解
监控项目及使用模板 监控http和https: Template App HTTP Service Template App HTTPS Service 监控cpu,内存,网络等: Templ ...
- Jmeter(十七) - 从入门到精通 - JMeter后置处理器 -上篇(详解教程)
1.简介 后置处理器是在发出“取样器请求”之后执行一些操作.取样器用来模拟用户请求,有时候服务器的响应数据在后续请求中需要用到,我们的势必要对这些响应数据进行处理,后置处理器就是来完成这项工作的.例如 ...
- Spring ApplicationContext 简解
ApplicationContext是对BeanFactory的扩展,实现BeanFactory的所有功能,并添加了事件传播,国际化,资源文件处理等. configure locations:(C ...
- HTTP协议简解
1.什么是http协议 http协议: 浏览器客户端 与 服务器端 之间数据传输的规范 2.查看http协议的工具 1)使用火狐的firebug插件(右键->查看元素->网络) 2)使用 ...
- python函数基础以及函数参数简解
python中函数分为函数.内置函数Python所有的内置函数 自定义函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. ...
- AC题目简解-数据结构
A - Japan POJ 3067 要两条路有交叉,(x1,y1)(x2,y2)那么需要满足:(x1-x2)*(y1-y2)<0判断出这是求逆序的问题 树状数组求逆序,先通过自定义的比较器实 ...
随机推荐
- c++中比较好用的“黑科技”
切入正题,上黑科技 一.黑科技函数(常用的我就不写了,例如sort函数) 1.next_permutation(a+1,a+1+n) a[1-n]全排列 2.reverse(a+1,a+1+n) 将a ...
- python默认参数问题
我们在定义默认参数时,有时会遇到一写似乎难以理解的问题.比如,在第二次调用函数时,默认参数记住了上一次执行的结果: >>> def test(L=[3,]): ... L.appen ...
- Oracle性能优化小结
Oracle性能优化小结 原则一.注意where子句中的连接顺序 Oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须卸载其他where条件之前,哪些可以滤掉最大数量记录的 ...
- word2010文档如何隐藏右侧灰色空白不可编辑区域
word2010文档如何隐藏右侧灰色空白不可编辑区域, (word2007也是差不多的操作) 两种方法: 1.点击图中的“最终状态”按钮: 2.点击图中的”以嵌入方式显示所有修订“的按钮:
- vue :style 动态绑定style
<div class="right userPicture" :style="[{'background':`url(${userImg}) no-repeat c ...
- Jdk8中Stream流的使用,让你脱离for循环
学习要求: 知道一点儿函数式接口和Lambda表达式的基础知识,有利于更好的学习. 1.先体验一下Stream的好处 需求:给你一个ArrayList用来保存学生的成绩,让你打印出其中大于60的成绩. ...
- maven加载ojdbc14报错
问题复现步骤: 1.在pom.xml里面添加ojdbc14的依赖,代码如下: <dependency> <groupId>com.oracle</groupId> ...
- 利用 Ruoyi 开发自己的业务管理系统__测试结构完成
前言铺垫不多说 (1)Ruoyi这个平台不错:如果你觉得你比Ruoyi的作者牛逼,你就不用看我这个文章了,你可以走了,因为我自认为比Ruoyi的作者要烂: (2)必须已经成功搭建Ruoyi,并能在自己 ...
- GAN网络进行图片增强
GAN网络进行图片增强 基于Tensorflow框架 调用ModifyPictureSize.py文件 代码如下: from skimage import io,transform,color imp ...
- python假设一段楼梯共 n(n>1)个台阶,小朋友一步最多能上 3 个台阶,那么小朋友上这段楼 梯一共有多少种方法
我们先把前四节种数算出来(自己想是哪几类,如果你不会算,那就放弃写代码吧,干一些在街上卖肉夹馍的小生意,也挣得不少) 标号 1 2 3 4 种类 1 2 4 7 ...