Java虚拟机的内存模型

java

一、问题起源

  这篇文章的起源其实是博主想要学习Java并发,计算机程序需要并发运行的原因在于:一方面cpu越来越多核化,另

一方面就是cpu和存储以及通信子系统的速度差距太大,粗略来说,cpu速度是ns级,内存100ns,硬盘ms,内存比cpu慢100倍,

硬盘比cpu慢100万倍,如果cpu需要等待这些速度慢的多的小伙伴,势必造成计算资源的浪费。

物理机为了解决cpu与内存的速度差,在两者之间加入了缓存,有缓存就会引入新问题,即缓存一致性问题。

      图1(图片来自参考文献【1】)

  为了解决缓存一致性问题,各个cpu在访问缓存和主内存时需要遵守一定的缓存一致性协议,

而把对特定的内存和缓存的访问过程抽象出来,就称之为“内存模型”。

二、JVM的内存模型

  如下图所示,与物理机中cpu访问内存的结构类似,JVM内存模型中,所有变量都存储在主内存(Main Memory)

每条线程有自己的工作内存(Working Memory),变量在不同线程间的传递需要通过主内存。

        图2(图片来自参考文献【1】)

  如上所述,变量在线程间的传递需要工作内存和主内存间的交互。这种交互要遵循一定的一致性协议。

这里简单称为“交互协议”,交互协议具体体现为8中原子操作和一些操作规则,如下:

>8种原子操作

  1. lock:作用于主内存的变量,把一个变量标识为一条线程独占的状态;
  2. unlock:作用于主内存的变量,把一个变量从一条线程独占的状态释放出来,释放后的变量才可以被其他线程上锁;
  3. read:作用于主内存的变量,把一个变量从主内存传输到线程的工作内存,这一步仅仅是传输动作;
  4. load:作用于工作内存的变量,把read中传输过来的变量放入工作内存的副本中;
  5. use:作用于工作内存的变量,把工作内存中的一个变量传递给执行引擎,即线程在读取变量的值;
  6. assign:作用于工作内存的变量,把一个从执行引擎接收到的值赋给工作内存的变量,即线程在写变量的值;
  7. store:作用于工作内存的变量,把一个变量的值传输到主内存,这一步仅仅是传输动作;
  8. write:作用于主内存的变量,把store过来的变量值放入主内存的变量中。

>操作规则

  1. 不允许read和load,store和write操作之一单独出现;
  2. 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变量同步到主内存中;
  3. 不允许一个线程无原因地(没有发生过assign操作)把数据从线程的工作内存同步到主内存中;
  4. 一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化的变量,也就是说变量在use,store之前必须先执行了assign和load操作;
  5. 一个变量在同一个时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,而且,多次lock后,必须执行相同次数的unlock才能解锁变量;
  6. 如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用变革变量前,需要重新执行load或assign操作初始化变量;
  7. 如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定住的变量。
  8. 对一个变量执行unlock操作前,必须先把此变量同步回主内存中(执行store, write操作) 。

此外,volatile关键字比较特殊,需要单独说明:

  volatile关键字具备两种语义特性:

  一是保证变量对所有线程的“可见性”,即对于volatile变量,当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。

  二是禁止指令重排序优化,

未完待添加。。。

  并发环境下访问内存是否安全。

参考文献:

【1】深入理解Java虚拟机 by 周志明

【2】Java并发编程实战 机械工业出版社2012

以上是 Java虚拟机的内存模型 的全部内容, 来源链接: utcz.com/z/394160.html

回到顶部