volatile底层实现

volatile可以保证多线程数据可见性和指令重排序,之前的文章我写了怎么使用,今天聊聊原理。
首先说一下cpu乱序执行
什么意思呢?即cpu并没有按照指定的指令顺序操作,cpu乱序执行提高了效率,相当于异步操作,如果多个cpu操作互相之间没有关联,是最理想的,但如果cpu之间操作的指令是关联的,并且没有按照理想的顺序操作,就会出现问题(指令重排序),cpu的速度比内存快很多。
什么是有关联的指令呢?
如创建对象的过程:
在这里插入图片描述
一个小例子证明cpu乱序执行
在这里插入图片描述我们的代码是从上到下的顺序解释执行,解释成汇编码,然后JVM执行。
例子中a和b在x和y上面,如果所有的指令都是顺序执行,那么a和b永远不会都==0。

经典的DCL(double check lock)单例模式
在这里插入图片描述
volatile 关键字可以保证变量会直接从主存读取,而对变量的更新也会直接写到主存
volatile如何解决指令重排序呢?
JVM层面的规定,所有jvm的实现,volatile修饰的内存必须指令有序执行,此概念为内存屏障。可以理解为内存前后加两堵墙
内存屏障是如何保证顺序呢?
在这里插入图片描述
JVM层面规定实现以下四种内存屏障load读store写
LOADLOAD
STORESTORE
LOADSTORE
STORELOAD

happens before 也是JVM的规定
表明有哪些程序执行过程中不可以指令重排序(有8个,如必须启动才能操作等最基础的环境等)
as if serial
单线程不论如何重排序,结果不会改变
多线程,有线程安全问题
以上为volatile指令保证了防止指令重排序
————————————————————————————
下面说一下volatile如何保证了线程可见性
cpu到内存读取数据会经历一系列的缓存过程。volatile的底层是lock addl汇编指令完成的,lock指令都做了什么呢?(P6处理器后lock指令锁缓存行)
1.可以将当前处理器对应的缓存内容立即刷到内存
2.同时将其他的处理器缓存失效,必须去内存读取自己刚刚刷新的数据,此为缓存一致性协议MESI(缓存一致性协议有很多种,此为其中一种)

多数情况下cpu读取内存数据是块级别读取,此为缓存行,大小为64字节。
多cpu是可以并行的,高速缓存会带来缓存数据不一致的问题
多核CPU==》几个核共享一个三级缓存L3,每个核都有自己的L1和L2。
每次缓存读取不会只读取对应数据,而是将对应数据的一块一起读取出来,但如果是这样也会引发一个问题,图上已经标出,缓存间的同步,也是需要耗时间的,所以引入了storebuffer,cpu异步处理。
CPU访问内存,基于总线通信
在这里插入图片描述

JMM8种原子数据操作:

read读取—>主内存读取数据。早期的lock是在这里加,最后write的时候释放,粒度太大
load载入—>将主内存数据写入工作内存
use使用->从工作内存取出数据计算
assign->赋值 将计算好的值赋值到工作内存中
store->存储 将工作内存数据写入主内存。后期的lock指令是在这里加锁,直接写操作加锁,速度很快
write->将store过去的变量赋值给主内存变量
lock->将主内存变量加锁,标记为线程独占状态
unlock-释放主内存变量的锁

来看一下详细过程
在这里插入图片描述

CPU的高速缓存L1L2L3 存在的意义:
内存速度比CPU慢成百上千倍,如果没有高速缓存,CPU在内存读取数据时就会阻塞等待内存的返回结果,造成cpu浪费
lock指令解决了可见性(缓存锁-粒度小/总线锁(old)-粒度大)和有序性(超级屏障,lock前后必须有序执行)
lock addl 后为什么是0呢?因为lock指令不能单独存在,必须跟指令,要不然上锁干啥呢?
两个volatile修饰的字段在同一个缓存行,性能会下降
如何解决呢?
1.8之前利用Long p1,p2,p3,p4,p5,p6,p7解决,long占8字节,7个为56字节,加上读取的数据正好64字节,这样就将读取的数据块分隔开来,减少了缓存同步的时间,1.8之后引入@sun.misc.Contended注解,保证作用的数据单独共享缓存行,Java11以后集成到了jar包里,这里不详细说明,后续文章会介绍disruptor的相关内容。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值