volatile

说一下volatile
volatile是java中修饰属性的关键字,是一种轻量级的同步机制:可以保证可见性,防止指令重排序,可以保证读写单操作的原子性 ,复合操作不能保证。 单操作的读写原子性很难证明,所以就别说了。

volatile有那些特性,及原理
可见性:MESI缓存一致性协议,解决多核CPU的情况下有多个一级缓存,保证缓存内部数据的一致,不让系统数据混乱。CPU嗅探是现代x86cpu的实现缓存一致性的方法,原来是锁总线,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,保证可见性,过期了会重新加载到内存,不是寄存器。
有序性:防止指令重排序(double check),体现有序性。在java中 对volatile编译的时候,会加内存屏障,防止指令重排序。
原子性:读/写单操作的原子性,复合操作不能保证,volatile底层主要是通透汇编lock前缀指令实现的,IA-32软件开发者手册对lock指令解释:锁定缓存并立刻写回主存,如果说volatile有原子性的话,那这里可以看做是一个原子操作。

系统架构上是怎样实现变量同步的?是怎样实现可见性的
在这里插入图片描述
早期cpu架构保证有序性是怎么做的
对总线进行加锁,导致所有线程和主存交互的操作暂停,只有一个拿到锁的线程在进行交互

后来使用mesi协议和cpu嗅探机制进行优化
在这里插入图片描述
mesi协议(缓存一致性协议):多个cpu从主存中读取一个数据到工作内存中,当某一个cpu修改了缓存里的数据,该数据马上会同步回主存,其他cpu通过总线的嗅探机制可以感知到数据的变化从而将自己工作内存中的数据置为失效

不能保证原子性 怎么实现i++
借助synchronized可以实现
在这里插入图片描述

为什么double check了,还要volatile
volatile防止指令重排:a=new A(),正常的顺序是三步
1.分配内存空间
2.将对象初始化到此内存中
3.将引用指向这个内存
cpu为了提高效率会将这三个指令重排序,如果变成了1 3 2,行在执行三后卡壳,线程二去访问这个不为null的对象就会出现异常

什么是指令重排序
多核cpu中的单核中也有多道流水作业。一段代码在执行前会经历多次排序,使无关联操作同时执行,提高执行效率,jvm在重排序的时候会加上一些内存屏障,保证内存的可见性。

volatile保证指令重排序怎么实现的
插入内存屏障
在这里插入图片描述

什么是内存屏障
http://www.elecfans.com/consume/578898.html
CPU执行或编译器指令优化,使得使读写乱序,我们插入一些指令解决这些问题,就引入了内存屏障,也称内存栅栏,内存栅障,屏障指令等, 他是由一类同步指令组成的。

jvm内存八大屏障指令
1.read:读取,从主存中读取数据
2.load:载入,读取主存数据到工作内存
3.use:使用,从工作内存读取数据进行计算
4.assign:赋值,将计算好的值重新赋值到工作内存
5.store:存储,将工作内存中的数据写到主存
6.write:写入,将store过去值赋值给主存变量
7.lock:锁定,将主存变量加锁,标识为被线程独占
8.unlock:解锁,将主存变量解锁,解锁后其他线程可以锁定改变量

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值