Volatile

Volatile

  • 处理器和内存之间的速度差异过大,所以在它们之间引入了高速缓存。高速缓存很好的解决了处理器和内存之间的矛盾,但也引入缓存一致的问题,每个处理器都有自己的高速缓存,但他们共享一块主内存。

处理器、高速缓存、主内存间的交互关系

  • 除了增加高速缓存之外,为了使得处理器内部的运算单元能尽量被充分利用,处理器可能会对输入代码进行乱序执行(Out-Of-Order Execution)优化。

一、缓存一致性协议

早期保证一致性,通过锁住总线,但是锁住后其他CPU无法访问内存,导致效率低下,引入MESI等缓存一致性协议.

  • Modify(修改):当前CPU修改变量值,其他的CPU也存在该变量副本。当前CPU缓存行状态为M
  • Exclusive(独占):当前CPU独占,其他CPU没有该变量副本。当前CPU缓存行状态为E
  • Shared(共享):各个CPU的高速缓存和主内存一致,CPU的缓存行状态为S
  • Invalid(无效):当前CPU修改变量值,其他CPU的缓存行状态为I

例如对应共享变量a,CPU1和CPU2的缓存行状态为s,当CPU1修改变量a时,会修改缓存行状态为M,通知CPU2的使得CPU2缓存行为无效状态,CPU2对变量进行读写时发现缓存为无效状态,则重新从主内存读取。CPU的监听和通知通过总线的嗅探机制实现。

虽然MESI保证了可见性,但是不能保证有序性,可以存在以下重排序情况:

  1. JIT编译优化
  2. CPU自身优化
  3. store buffers下会导致的看似“重排序”的现象(为了解决经典MESI下写核心等待其他核心invalid ACK的,造成同步阻塞的问题,引入了store buffers硬件层面进行异步优化)

使用Volatile,底层使用Lock#前缀指令,Lock前缀指令有内存屏障的作用,防止指令前和指令后的重排序。同时Lock指令会进行缓存锁定,使得其他CPU无法访问,同时Lock前缀使得store buffers刷入缓存行(其他CPU读取该变量时,发现缓存行的状态为I,同时存在其他缓存行状态为M-即刚才store buffers刷入缓存行,这时会先让该缓存行-M的数据刷入内存,然后CPU从内存读取,其实就是缓存一致性协议MESI),同时使得其他cpu或者内核无效化,通过MESI保证可见性。

二、Java内存模型

  • 变量存储在主内存中,每个线程都有自己的工作内存,线程会先将变量拷贝到工作内存中,在工作内存进行变量的操作,工作内存只对线程自身可见,其他线程不可见。变量操作完后会刷入主内存。

三、内存屏障

  • 读后面插入两道屏障,LoadLoad和LoadStore屏障
  • 写前后插入两道屏障,前插入StoreStore后插入StoreLoad
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值