volatile关键字原理解析

本章在讲述Volatile关键字之前,我们先大概讲一下cpu多核并发缓存架构,再到JMM,即java内存模型,最后到volatile关键字。

1、JMM(Java内存模型)

多核并发缓存架构的引入

为了解决CPU和主内存速度交互的不匹配问题,计算机在设计的时候在中间加几级缓存(一般放在CPU内部的,这里是为了好看画到中间了),高速缓存读取速度非常快,CPU和高速缓存交互,程序结束后,会把缓存中的数据同步到主内存再回写到硬盘。
在这里插入图片描述
而Java线程的内存模型和CPU缓存模型是类似的,是基于CPU缓存模型建立起来的。Java线程的内存模型是标准化的,屏蔽掉了底层不同计算机的区别。如下图显示:
在这里插入图片描述
和CPU一样,线程A为了解决跟主内存速度不匹配问题,会把这个共享变量copy到线程的工作内存。线程读取共享变量数据是和工作内存中变量的副本做交互。这里的工作内存类似于缓存。

2、JMM数据原子操作

JMM有8个原子操作,按照使用流程来排序,分别如下:
在这里插入图片描述

在这里介绍java的数据原子操作,是为了更好的为下面的问题铺垫。


3、CPU缓存不一致问题

对于多核CPU而言,当共享变量同时被加载到缓存中并在多个核心中都同时进行操作时,当核心A修改了变量a后,核心B不知道a已经做了修改,继续推进核心B的线程工作,这样子,程序就会出现问题,因此就存在了缓存不一致问题。

为了解决CPU缓存不一致问题,工程师主要使用了两种方式。早期主要使用总线加锁方式。

总线加锁:即cpu从主内存读取数据到高速缓存,会在总线对这个数据加锁,这样其他cpu核心没有办法去读或者写这个数据,直到这个cpu使用完数据并释放锁之后,其他cpu核心才能读取该数据。该方式可以用java内存模型和java数据原子操作来体现,如下图:

在这里插入图片描述
当一个线程读取主内存中某个变量的时候,就会对这个变量加锁,其他CPU(线程)想从主内存读这个变量的数据是读不到的,直到这把锁释放了才能读取到该变量的值,并在其他CPU中做运算。在read之前会执行lock操作,标识为线程独占状态,在write写回主内存的时候会做个unlock操作,解锁后其他线程可以锁定该变量。早期的CPU为了解决可见性,一致性问题,把一个并行执行的程序最终变成串行执行。

显然该方案不可行,后来,工程师使用了MESI缓存一致性协议来解决该问题

MESI缓存一致性协议:多个cpu从主内存读取同一个数据到各自的高速缓存中,当其中某个cpu修改了缓存里的数据,该数据会马上同步回主内存,其他cpu通过总线嗅探机制可以感知到数据的变化从而将自己缓存里的数据失效.
如下图:
在这里插入图片描述

CPU和内存之间通过总线相连接。各个线程都从主内存中读数据,实现了并行。当线程2修改initFlag变量后,执行store操作时,此时会把这个工作内存中修改的数据initFlag=true变量的值回写到主内存中,最后执行write替换主内存中的值。一旦执行store此原子操作,该数据会通过总线回写到主内存,MESI缓存一致性协议有个CPU总线嗅探机制(通过硬件实现):当其中某个线程(这里是线程2)把修改的变量的值从工作内存往主内存回写的时候,只要数据通过总线,其他的CPU(这里是线程1)会对这个总线做一个监听,对总线中感兴趣的变量不断监听数据流动,发现有其他CPU(这里是线程1)感兴趣的变量的时候,MESI缓存一致性协议就会通过总线嗅探机制把这个其他CPU(这里是线程1)中工作内存中的同一个变量的值置为无效。然后线程1再执行循环操作的时候,发现initFlag失效了,就重新从主内存去readinitFlag,而此时主内存中的initFlag已经被修改过了(为true),线程1就能拿到最新的值了。就能通过MESI缓存一致性协议和总线嗅探机制可以让程序达到缓存一致性。

4、java代码演示不可见性

说完了CPU缓存不一致解决方案,接下来,我们通过java代码演示一下多线程下缓存不一致性的问题,也称为不可见性。

public class JMM {
   
    private static  boolean initFlag = false;

    public static void main(String[] args) 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值