J.U.C volatile , CAS 原理总结
- 并发编程的相关概念
由于计算机执行指令的速度要大于物理内存(主存)数据IO的速度,所以为了避免重复多次的IO操作,引入了告诉缓存的概念,用于存放IO的数据,提高程序执行的速度。我们的JAVA程序呢,每个线程都有自己私有的高速缓存区域。涉及到数据的使用时,就会从主存拷贝到高速缓存区,写出的时候,先写入自己线程私有的缓存区,再刷新到主存中的数据。
i = i +100 ;
比如这行代码,首先是从主存读取i的值到缓存区域,然后计算后更新告诉缓存区域的i值,再根据缓冲区的i值区刷新主存里面的i值。这个流程当遇到并发的时候,就会有缓存不一致问题出现,这个情况是有cpu的调度引起的。
假设现在有2个线程A和线程B 同时对变量i (初始值为0) , 进行 +1 的操作,单个线程要+1的话,会分为读取,计算和赋值等多个步骤,线程A再读取i值为0完成,计算之前,线程B被cpu调度,读取到的值也为0,那么这个时候线程A计算完成并修改完成为1,线程B计算i的初始值为0,+1之后也是1,在冲刷到主存,这个时候两个线程共同作用的结果并不符合我们预期。
即操作不可中断,要么成功,要么失败。我们执行上面例子中的代码涉及到读取修改和赋值更新几步操作,就丢失了原子性
上面例子中的步骤当更新完i缓存中的值然后再更新主存中的值,分为两步,2个过程也可以因为cpu调度发生中断,导致并不会第一时间更新主存的值,其他线程读取的时候还是A线程未修改之前的值。不能第一时间读取到最新修改后的结果,就会失去可见性。
只是更新值到工作内存中。高速缓存的同步更新由可见性的volatile实现。
-
原子性
-
可见性
-
有序性
这个涉及到JAVA编译期间,为了优化字节码,做的一些指令重排序的操作。
知道了上面这几个并发编程的概念,我们引入CAS作为解决原子性的问题解决方法
后面更新
引入volatile解决共享变量的可见性问题和指令重排问题。