Java并发之volatile



1:概念

JMM即Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内
存、CPU指令优化等。

2:解决的问题

JMM体现在以下几个方面

  • 原子性-保证指令不会受到线程上下文切换的影响(比如说是n++,如果发生线程上下文切换的话,那就破坏了这一条指令的执行)
  • 可见性-保证指令不会受cpu缓存的影响
  • 有序性-保证指令不会受cpu指令并行优化的影响

3:可见性

(1):问题的引出

可见性是指一个线程对一个变量进行修改,另外一个线程可以看的到
可见性问题是由CPU的缓存导致的,多核CPU均有各自的缓存,这些缓存要与内存进行同步。(其实就是多线程环境下,一个线程对一个变量的改变了,而另一个线程没看到,那么的话还是按照原来的变量的值进行计算的话,那么就会出错)。

(2):如何解决

我们可以对该变量加上 volatile 关键字,这样的话,每次线程都是从主存中去取变量,这样就解决了缓存中数据与主存中数据不一致的问题。我们也可以使用关键字 synChronized 关键字来进行解决可见性问题,只不过synChronized是重量级锁,会影响性能。

(3):拓展

  • volatile适合在一个写线程和多个读线程中使用,只能保证变量在内存中的可见性,并不能防止上下文切换带来的原子性问题。
  • 但是对变量加上 volatile关键字并不能接解决 原子性问题;但终归还得是靠老大哥synChronized来上锁,既能防止上下文切换解决原子性问题,也可以解决变量可见性问题。

4:有序性

(1):问题的引出—指令重排

为什么会有指令重拍呢,主要是CPU进行优化,提高处理速度造成的。一条指令可以分为 取指令·指令译码·执行指令·内存访问·数据写回 CPU可以在一个时钟周期内,执行不同指令中的不同阶段,也就是同时将5条指令同时进行中,那么其实这样的话,就会出现指令重排问题,因为在一个CPU时钟周期内,我们执行的不是一条完整的指令。

(2):如何解决指令重拍呢

主要也是在相关变量上加上 volatile关键字

5:volatile原理

(1):内存屏障

  • volatile的底层实现原理是内存屏障,Memory Barrier(Memory Fence)
  • 对volatile变量的写指令后会加入写屏障
  • 对volatile变量的读指令前会加入读屏障

(2):如何保证可见性呢

  • 写屏障:保证在该屏障之前的,对共享变量的改动都同步到主内存中
  • 读屏障:保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据
    在这里插入图片描述

(3):如何保证有序性呢

  • 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
  • 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前
  • 其实也就是有了内存屏障,那么就有了有序性。
    在这里插入图片描述
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天向上的菜鸡杰!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值