Volatile关键字解读(一)

volatile关键字很多人都听说过,但真正使用起来并不是那么简单容易,因为这关系到很多内存模型相关的知识点,本人最近在网上翻看了很多资料,在此做一下总结,根据前人的经验,我主要从四个方面进行解读:

* 内存模型的介绍
* 并发编程的三个要素
* Java内存模型
* volatile的原理和用法

最后会结合几个实例进行详细的说明

内存模型介绍

接触过操作系统和编译原理的人都知道,程序运行最终是通过指令来实现的,而指令是在cup中执行的,cup的计算速度相当的快。程序在执行过程中会涉及到数据的读取和写入,通常这些数据都是存储在主存(也就是通常说的内存)中,我们试想一下当cup在高速运行,这个时候需要读取或者写入计算结果,此时cup会一直等到去内存获取数据,这明显拖慢了cup的运行速度。

为此cup引入了高速缓存(cache)这个概念,即每个cup会有独立的一个高速缓存区,cup所需的数据会先从内存中拷贝一份备份数据到高速缓存,然后cup会使用高速缓存中的数据进行计算,计算结果也会存储到高速缓存中,最后cup会将高速缓存中的结果回写入内存中,完成数据的读取的和写入操作。

举例说明一下

i = i +1;

首先cup会将i这个变量的值从内存拷贝到高速缓存中,然后在缓存中对i进行加1操作,最后在将结果回写入内存中

我们来一起分析一下上面的操作过程,首先将i从内存拷贝到高速缓存中,在高速缓存中对i进行操作,然后才回写内存,那这中间就会导致内存中i的值和高速缓存中i的值会出现短暂的不一致,而这种不一致在单核cup中是没有任何影响的,因为单核cup我们可以理解成是一个顺序执行程序的通道,一次只能执行一个程序;但对于现如今多核cup来说就会出现结果不一致的并发问题

假设此时cup1和cup2都要对i进行运算操作
cup1首先从内存中获取i的拷贝到对用的高速缓存中,然后对i进行加操作
cuo2这个时候也从内存中获取到i的拷贝,同样对i进行加操作
然后cup1和cup2都将计算后的结果回写入内存中,结果i = 2,而实际上i的值应该等于3

以上问题就是著名的缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。也就是说一个共享变量在多个CPU中被使用(常见于多线程问题中),就会出现不一致问题

为了解决缓存一致性问题,很早以前主要通过以下两种方式

  • 在cup总线上加lock锁

  • 通过缓存一致性协议

这两种方式都是在硬件层面上的处理

总线加锁

很早以前是通过在总线上加锁来实现一致性的,我们都知道cup是通过总线去访问内存区域的,当cup要访问内存的某个区域时,我们在总线上进行加锁操作,那么这个时候其它cup就无法访问该内存区域,只有等到总线锁释放后其它人才能访问到该区域中的数据,这就解决了缓存不一致的问题。

但总线加锁这种方式有个缺陷就是会阻塞cup,当两个cup同时访问一个内存区域时,只会有一个cup能拿到这个总线锁,势必会导致另一个cup阻塞等待,拖慢了cup的速度,因此后来就出现了缓存一致性协议。

缓存一致性协议

缓存一致性协议最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当cup在操作某个变量时,如果发现这个变量是一个共享变量,它就会去发消息信号通知其它cup的高速缓存置该变量的拷贝副本为无效状态,当其它cup要使用这个变量时发现变量状态是无效状态,就会去内存中重新获取数据的拷贝值,这样就可以实现缓存的一致性。




参考信息来源:
http://www.cnblogs.com/dolphin0520/p/3920373.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值