06Volatile关键字

Cache(三级缓存)的出现是为了解决cpu(贼快)和内存(相比cpu慢的多,但是redis也是基于内存的数据库,一旦程序关闭(也就是redis退出),那么内存中存储的缓存都会消失,而redis在启动时通过aof或rdb将数据重新读取到内存中来,扯远了。。。。。。)之间读写速度严重不统一的问题

CPU缓存一致性问题:i++

首先,在程序运行期间,将主内存中的数据复制一份存储到CPU Cache中,那么cpu寄存器在进行数值计算的时间就直接到Cache中进行读写,等到整个过程结束,再将Cache中的数据刷新到主存中。但是在多线程的情况下:这很容易造成数据不一致

Java内存模型

假设主内存给共享变量为0,线程1和线程2分别共享变量X的副本,假设线程1此时将工作内存中的x修改为1,同时刷新到主内存中(但是这个刷新时间并不确定),若线程2想去使用副本x的时候,会发现变量已经失效,必须到主内存中再次获取存入到自己的工作内存中,这点与CPU和CPU Cache之间的关系非常相似。看起来似乎没什么问题,但是若此时两个线程都同时修改自己工作内存为1,然后先后刷新主内存,那么就会造成数据不一致

JVM的读取,赋值操作都是原子性的不可被中断的,但是volatile关键字不具备原子性的语义

volatile关键字:一个线程修改了volatile修改的变量,另外一个线程会立即看到修改的最新的值:

比如:

  1. reader线程从主内存中获取值为0,将其缓存到本地内存中
  2. update线程将自己的本地内存的值修改为1,然后立即刷新到主内存(注意:这里是立即刷新,那为什么还不能保证原子性呢?看下面解析)
  3. reader看到自己本地内存的值失效(因为刷新后,会去通知拥有副本的值都失效),因此到主内存中重新读取值

这样就保证了可见性

但是i++并不是原子性的,若此时两个线程都同时修改自己工作内存为1,然后先后刷新主内存,就会导致数据不一致

 

volatile和synchronized的区别

  • volatile只能修饰变量
  • synchronized只能修饰方法,语句块
  • volatile修饰的变量可以为null,synchronized关键字修饰的同步语句块的monitor对象不能为null

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值