Java voliate和AtomicInteger的简单理解

Java voliate和AtomicInteger的简单理解

经常在源代码中看到voliate和AtomicInteger,然后上网会搜出一大堆的特性,看了别人的分析介绍后,大概总结了下voliate和AtomicInteger的原理,记录一下。

首先我们比较熟悉的java内存模型。
在这里插入图片描述
java为什么要定义内存模型呢?是为了让程序员能够专注于程序本身,而屏蔽掉了具体硬件与系统的交互细节实现。其实,主内存就是我们加载程序,放置对象的内存,也是硬件里面的内存,而工作内存,就是CPU的寄存器,一级缓存、二级缓存、三级缓存等。

那voliate有什么用呢?其实就是我们申明某个变量是voliate之后,该变量被编译成字节码文件的时候会被额外的增加指令,通过这些指令,jvm可以控制cpu从内存读取数据运行的方式。那常见的程序是怎么运行的呢?正常我们所有的程序被编译成字节码之后,指令会被加载到主内存,cpu在执行某个线程的指令的时候,会加载这些指令到cpu缓存然后解释执行指令操作,比如发现是运算的话,会将主内存的变量加载到工作内存(不是拿过来,而是复制了一份),也就是cpu的一级、二级、三级缓存,为什么这样做?因为计算的时候会产生很多中间结果,如果频繁的产生一个结果就把结果放到主内存,会效率很低,就好比cpu计算好花费了1秒钟,把结果放进内存等了一天,又等了一天才把中间结果加载到cpu,cpu都闲死了。等数据加载到cpu缓存后运算结束后再将结果放回到主内存,这就是正常的程序处理逻辑。但是,有不正常的时候,什么时候呢,多个线程访问同一个主内存变量,比如,线程A从主内存中加载了整数0,准备计算,计算到一半的时候,cpu让这个线程让出cpu资源,这个时候cpu会为这个线程保存线程数据,就是常说的上下文(所以不要频繁切换线程,有额外工作啊),线程B也同样从主内存加载数据计算,计算结束后把数据存储到住内存,这时候线程A又开始从保护现场继续执行,结束后数据被送到主内存,这时候主内存的数据发现只是执行A线程的数据,B线程相当于没有执行。

voliate能做点什么呢?
有俩点:1 申明了voliate的变量在cpu执行的时候,如果线程不执行了,cpu不会缓存voliate变量的线程,这就导致线程恢复后继续执行的时候,必须从主内存读取数据,这样就能实时拿到变化后的数据。
2 申明了voliate的变量在cpu执行赋值操作的时候,必须以原子性操作写回到主内存。原子性就是cpu执行的时候要么不执行,要么必须不间断的执行完。

这样,对voliate变量的改变就会被其他线程执行时感知到,这就是voliate的可见性。

AtomicInteger是什么呢?voliate的变量已经可以保证变量变化被感知到了,线程同步是不是解决了?不是的,因为voliate变量只是保证了赋值操作的原子性,那么如果在计算这个变量值的时候线程被切换了呢?还是有问题。为了解决这个问题,AtomicInteger来了,看他的源代码就发现他的内部值也是voliate声明的,那么只要保证voliate声明的变量运算的时候原子性就好了,AtomicInteger保证运算原子性的原理是内部是CAS,CAS的全称是Compare-And-Swap,它是一条CPU并发原语。它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。因此,AtomicInteger可以保证线程间数据同步问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值