JMM内存模型:
这个简单来说就是一个规范,对数据进行计算的时候先从主内存中读取到PC寄存器然后进行计算之后将计算的结果最后再放入到主内存中
下面以 i++的计算过程为例子:
引申出这种情况下的三大特性(线程安全):
1.原子性: 当线程对资源进行操作的时候不能被其他线程所打断
例子: 简单来说当我有多个线程对i 进行+1操作的时候总共1万次那么最终i的结果也必须是一万次
2.可见性: 当一个线程对共享资源进行操作完成之后其他操作的线程会立刻得到这个线程操作之后的结果
例子: 当我一个线程将 i从0变为1的时候 ,那么其他线程对i操作的线程进行+1操作的时候必须是对i=1这个值进行一个操作
3.顺序性:程序的编写的顺序和执行的顺序是一致的不会出现指令重排序
指令重排序:在我看来就是一个优化的手段 分为:
编译器重排序:编译器会重新安排指令的顺序
处理器重排序:可以先执行某个指令也可以后执行某个指令
但是无论是哪种重排序都不能影响最终的正确的结果
Volatile关键字(只能解决顺序性以及可见性但是不能解决原子性)
原因:
1.解决可见性是通过MESI缓存一致性协议:
简单来说就是通过总线的事件监听来进行一个保证
每一个PC寄存器里面都是有三个缓存(L1 L2 L3)
从L1到L3是体积是越来越大的那么成本就是越来越低 速度相对来说也就是越来越慢(毕竟一分价钱一分货),那么PC获得数据的时候会优先从三个缓存中读取数据如果没有的话那么就会从主内存中读取数据(提高效率的一个过程)
如图:
2.解决顺序性是通过添加读写屏障:对数据进行读写操作的前后添加读写屏障
读屏障:会确保所有的读取操作都已完成,并且任何后续的读取或写入操作不会被重排序到此屏障之前。
写屏障:会确保所有之前的写操作都已完成
3.不能解决原子性的原因: 是因为有一种特殊的情况的发生,有可能会出现多个PC寄存器同时从主内存中读取数据,然后同时进行+1的操作然后再将计算之后的数据同时刷入到主内存中。
解决原子性的方法:
1.可以通过锁机制来进行一个限制(这个方法是比较降低整体的系统的性能的)
2.可以通过CAS操作通过对比一个版本号(这个就是为了解决ABA问题)来保证操作的原子性
CAS操作:
这个自旋是可以进行控制的
ABA问题如图所示:
由于竞争CPU资源的原因导致线程2最后才进行操作,但是线程2在正常的情况下是操作失败了,但是由于线程3的操作使得线程2操作成功了,这个就是一个问题了
解决:添加版本号,当线程进行操作的时候处理比较数值还要比较版本号,如果版本号不对的话那么操作也是失败的
标签:版本号,线程,内存,Volatile,JMM,操作,排序,进行 From: https://blog.csdn.net/2201_75397629/article/details/142847870