volatile关键字

volatile关键字的作用
1、保证数据在各个线程间的可见性
2、禁止指令重排序

依照我的理解,其实禁止指令重排序就是为了保证数据的可见性,保证缓存一致性,实现这两点都是使用了同一个方法就是加入了内存屏障

1、内存屏障的是如何保证数据的可见性的
详细参考:http://www.wowotech.net/kernel_synchronization/Why-Memory-Barriers.html

我简要概述上述链接的内容,上述链接讲的是CPU的缓存一致性和内存屏障,其实Java的内存模型和CPU的内存模型差不多,但是更加粗犷一些,如图,没有store buffer这些精细化的内存管理,只是给多个线程每个分配了一个工作内存(相当于高速缓存),图虽然是CPU的内存模型,但Java的也是如此,将CPU换成thread就行
在这里插入图片描述
内存屏障主要分为读屏障和写屏障
写内存屏障(Store Memory Barrier):处理器将当前存储缓存的值写回主存,以阻塞的方式。
读内存屏障(Load Memory Barrier):处理器处理失效队列,以阻塞的方式。

详细来说:
写内存屏障,将缓存中的脏数据flush到主存中,同时通过CPU总线告知其他CPU其缓存中的该项数据已经失效,不能再使用,其他CPU就将这条消息存储到失效队列中。
读内存屏障,线程去缓存中读取数据之前,会先处理失效队列,失效队列会将缓存中的一些值置为失效状态,处理完后再去读取缓存的数据,如果读取的数据刚好是失效的,线程就只能去主存中去去最新的值,这样就确保了数据的可见性。

在每个volatile写操作前插入StoreStore屏障,这样就能让其他线程修改A变量后,把修改的值对当前线程可见,在写操作后插入StoreLoad屏障,这样就能让其他线程获取A变量的时候,能够获取到已经被当前线程修改的值
在每个volatile读操作前插入LoadLoad屏障,这样就能让当前线程获取A变量的时候,保证其他线程也都能获取到相同的值,这样所有的线程读取的数据就一样了,在读操作后插入LoadStore屏障;这样就能让当前线程在其他线程修改A变量的值之前,获取到主内存里面A变量的的值

虽然Java中的内存屏障分为StoreStore,StoreLoad,LoadLoad,LoadStore四种,但其本质还是读,写这两种内存屏障,在volatile写操作之后加入store屏障,在volatile读操作之前加入load屏障,这样就可以确保数据对所有的线程可见。

2、禁止指令重排序
详细参见:http://www.wowotech.net/kernel_synchronization/453.html

内存屏障可以禁止指令重排序,主要在编译器阶段就禁止了其重排序,在编译器检测到内存屏障之后就不会对屏障前后的代码进行重排序,保证其执行顺序

这样就可以到达:
写volatile变量时,可以确保volatile写之前的操作不会被编译器重排序到volatile写之后。
读volatile变量时,可以确保volatile读之后的操作不会被编译器重排序到volatile读之前。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值