内存模型

本人博客难懂的很,我写的东西有的我自己都看不懂(盲打的真正含义吧),你若看不懂请不要评论,我怕你;

 

在谈谈Java的内存模型之前,我们来看看物理上的内存;

首先,在单核电脑中,处理问题要简单的多。对内存和硬件的要求,各种方面的考虑没有在多核的情况下复杂。电脑中,CPU的运行计算速度是非常快的,而其他硬件比如IO,网络、内存读取等等,跟cpu的速度比起来是差几个数量级的。而不管任何操作,几乎是不可能都在cpu中完成而不借助于任何其他硬件操作。所以协调cpu和各个硬件之间的速度差异是非常重要的,要不然cpu就一直在等待,浪费资源。而在多核中,不仅面临如上问题,还有如果多个核用到了同一个数据,如何保证数据的一致性、正确性等问题,也是必须要解决的。
目前基于高速缓存的存储交互很好的解决了cpu和内存等其他硬件之间的速度矛盾,多核情况下各个处理器(核)都要遵循一定的诸如MSI、MESI等协议来保证内存的各个处理器高速缓存和主内存的数据的一致性。
Java内存模型
虽然Java程序是运行在Java虚拟机中,但是实际也是在物理内存上运行的。Java虚拟机只不过是开了一个容器,类似一个容器做了一个封装处理呗;
实际的Java内存模型是定义了Java中变量的访问规则;相关变量请看我的另一篇文章,Java各种变量;
这里的变量主要包括全局变量和成员变量还有各种数组,不包括局部变量和成员方法,因为他们都是线程私有的;
Java内存模型中涉及的几个概念:
1.主内存:Java中定义各种变量必须存到主内存中,也就是堆内存中。除了上述的局部变量哈;
2.工作内存:也就是Java虚拟机栈,或者栈内存,这里保存了所有运行程序需要的主内存中变量的副本,和该线程中需要的局部变量;
工作内存和主内存的交互
Java中线程的主内存和工作内存的交互提供了八种原子性的操作:
1.lock锁定,作用于主内存,使一个线程独占该变量;
2.unlock解锁,作用于主内存,对主内存中锁定的变量解除锁状态,恢复多线程占有;
3.read读取,作用于主内存,对主内存中变量进行读取给工作内存;
4.load加载,作用于工作内存,将从主内存中读取的变量加载到工作内存;
5.use使用,作用于工作内存,将加载的变量传递给工作引擎进行使用;
6.assign赋值,作用于工作内存,将工作引擎返回的值赋值给工作内存中主内存变量的副本;
7.store存储,作用于主内存,将赋值完的工作内存中的变量副本传递到主内存;
8.write写入,作用于主内存,将传递过来的变量副本的值写入主内存变量中;

如果要把一个变量从主内存传输到工作内存,那就要顺序的执行read和load操作,如果要把一个变量从工作内存回写到主内存,就要顺序的执行store和write操作。对于普通变量,虚拟机只是要求顺序的执行,并没有要求连续的执行,所以如下也是正确的。对于两个线程,分别从主内存中读取变量a和b的值,并不一样要read a; load a; read b; load b; 也会出现如下执行顺序:read a; read b; load b; load a; (对于volatile修饰的变量会有一些其他规则,后边会详细列出),对于这8中操作,虚拟机也规定了一系列规则,在执行这8中操作的时候必须遵循如下的规则:不允许read和load、store和write操作之一单独出现,也就是不允许从主内存读取了变量的值但是工作内存不接收的情况,或者不允许从工作内存将变量的值回写到主内存但是主内存不接收的情况不允许一个线程丢弃最近的assign操作,也就是不允许线程在自己的工作线程中修改了变量的值却不同步/回写到主内存

  • 不允许一个线程回写没有修改的变量到主内存,也就是如果线程工作内存中变量没有发生过任何assign操作,是不允许将该变量的值回写到主内存
  • 变量只能在主内存中产生,不允许在工作内存中直接使用一个未被初始化的变量,也就是没有执行load或者assign操作。也就是说在执行use、store之前必须对相同的变量执行了load、assign操作
  • 一个变量在同一时刻只能被一个线程对其进行lock操作,也就是说一个线程一旦对一个变量加锁后,在该线程没有释放掉锁之前,其他线程是不能对其加锁的,但是同一个线程对一个变量加锁后,可以继续加锁,同时在释放锁的时候释放锁次数必须和加锁次数相同。
  • 对变量执行lock操作,就会清空工作空间该变量的值,执行引擎使用这个变量之前,需要重新load或者assign操作初始化变量的值
  • 不允许对没有lock的变量执行unlock操作,如果一个变量没有被lock操作,那也不能对其执行unlock操作,当然一个线程也不能对被其他线程lock的变量执行unlock操作
  • 对一个变量执行unlock之前,必须先把变量同步回主内存中,也就是执行store和write操作

当然,最重要的还是如开始所说,这8个动作必须是原子的,不可分割的。

针对volatile修饰的变量,会有一些特殊规定。
 
 
posted @ 2020-10-28 11:56  瞌睡青年  阅读(58)  评论(0)    收藏  举报