volatile关键字的理解

volatile 是java的关键字,是JVM为了解决数据一致性的一种轻量级方案。volatile主要从内存可见性和指令从排序这两个方面来解决数据一致性问题。

随着计算机的发展 ,CPU的读写速度远远的大于内存的读写数据,而读写速度高的内存价格又比较高,所以在CPU之间和内存之间就加了缓存。目前大多数CPU和内存的交互图如下:

既然又了缓存,再加上现在都流行多核CPU,那就不可避免的会出现内存中数据和缓存中不一致问题。

为了解决数据不一致问题,可以有以下两种方案:

直写:

当某一个线程对某一个值进行更新操作时,直接把值刷新到内存中,同时直接更新其他缓存中为最新值。

回写:

当某一个线程对某一个值进行更新操作时,把值刷新到内存中,同时其他缓存嗅探总线上该值的变化,如有有变化,直接把该值置为失效。

但是在不同的计算机底层架构中,会有不同的具体的实现,java为了屏蔽底层的实现,java抽象了一个内存模型,来屏蔽具体的底层的实现。

java把内存模型(简称JMM)分为工作内存(本地内存)和主内存,其中工作内存是线程私有的,而主内存是线程共享的内存,工作内存或者称本地内存是抽象概念,它本身并不实际存在。它是寄存器,缓存等其他一些硬件和编译器上的一种抽象,它的实现还是依赖底层逻辑。

在java内存的模型中,如何线程A如果更改一个共享内存中的变量,更新后线程B如何此时已经缓存了一份在本地内存中,此时线程B是不知道A对该变量做了操作。

如果在该变量前面添加了一个volatile修饰符,当线程A对该变量做更新操作时,会及时把线程A本地变量中的副本同时刷新到主内存中,同时线程B中该变量的副本会立刻失效。可以理解为,被volatile修饰的变量更改时,会告诉CPU一个信号,把该变量的更改同步刷新到主内存中,而其他线程的把该变量的copy置为失效是通过计算机的缓存一致性协议实现的,被volatile修饰的变量会嗅探CPU总线上该变量的变动,如果有变动,则会把本地内存中的副本置为失效。

所以总结来说,volatile是JVM实现缓存一致性的一种实现方案。但是被volatile修饰的变量并不一定会线程安全。

从线程安全定义的角度说,如果一个变量是线程安全的,必须满足如下条件:

可见性:缓存中更改了该变量的值,必须同步到主存中。

有序性能:禁止指令重排序

原子性:对改变量的操作是一个原子操作。

 被volatile修饰的变量满足 可见性和有序性,但不满足原子性。

eg:当线程A操作变量X,经过的步骤有:

1:本地内存中赋值变量X的值

2:把X变量的最新值写回到主内存中

3:把其他对改变量有缓存的值置为失效。

当A线程执行本地赋值操作,但是还没有写回到主内存中时,如果线程B也对该X变量有了更新操作就会出现数据不一致问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值