本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

JVM03--JMM(JAVA内存模型)

发布于2021-05-29 21:23     阅读(1448)     评论(0)     点赞(8)     收藏(4)


1.物理机解决并发的方案

  • 解决的首要问题:CPU运算速度和物理机存储设备之间的存在的巨大速度差异
  • 解决的办法:通过在CPU和内存之间增加一层独写速度尽可能接近处理器运算速度的高速缓存,作为两者之间的缓冲。将CPU运算需要的数据复制到高速缓存中,保证运算能够快速的进行;当CPU运算结束后,再将运算结果从缓存同步回内存中,这样CPU无须再等待缓慢的内存独写(这里的缓慢是相对CPU处理而言的)。
  • 衍生的问题:基于高速缓存的设计方案能够很好地解决处理器与内存间的速度差异矛盾,但同时也引入了一个新的问题“缓存一致性”。在一个多核处理器系统中,每个处理器都有自己的高速缓存,而它们又共享同一主内存。当多个处理器的运算任务涉及到同一块主内存区域时,将可能导致各自的缓存数据不一致。为了解决这一问题,所以要求各个处理器之间遵循一些协议(如MESI:缓存一致性协议),来保证数据独写操作的正确性。

               

2.Java内存模型

2.1概述

       前面对物理机解决并发的方案及其衍生问题进行了一个简单概述,对于JAVA程序来说,并发问题主要解决两个问题:线程通信和线程同步。在多线程为共同完成同一任务而并发执行时,各个线程之间可能存在着数据交互或操作同一份内存数据,并且在执行顺序上存在先后关系,这时我们就需要在多个线程之间加入协调通信机制,来保证程序有序正常执行。线程之间的通信机制主要包括两种:共享内存和消息传递,Java采用的就是共享内存模型。Java多个线程之间通过读-写内存中的“公共状态”来进行通信,这个过程是隐式进行,对程序员来说是完全透明无感知的。为了定义上述“公共状态”的访问规则,抽象出Java内存模型(JMM),JMM决定一个线程对公共状态(共享变量)的写入如何对另一个线程可见。这里的“公共状态”从JVM的角度看指的是线程共享的数据区变量,包括:实例字段、静态字段和构成数组的元素,不包括局部变量和方法参数等,因为它们是线程私有的。

       JAVA内存模型规定了所有共享变量存储在“主内存”中,而每个线程还拥有自己的“工作内存”,线程的工作内存中保存了被当前线程使用到的主内存中共享变量的副本拷贝,线程对共享变量的操作都在工作内存中完成,不能直接独写主内存中的变量。同时,各线程直接也无法直接访问对方工作内存中的变量,线程之间变量值的传递需要通过主内存来完成。线程、工作内存、主内存三者之间的抽象关系如下图:

2.2内存间交互操作

变量如何从主内存拷贝到线程的工作内存,以及如何从线程工作内存同步回主内存,JMM定义了如下8中操作来实现上述两个过程:

  • lock(锁定):将变量标识为线程独有状态。
  • unlock(解锁):将一个处于锁定状态的变量释放,释放后的变量可以被其他线程使用。
  • read(读取):将一个变量的值从主内存传输到线程的工作内存中,以便后续的load操作使用。
  • load(载入):将完成read操作的变量值放入本地工作内存的变量副本中。
  • use(使用):将线程本地工作内存中的变量值传递给执行引擎,每当虚拟机遇到一个需要使用该变量值的字节码指令时将回执行该步操作。
  • assign(赋值):将一个从执行引擎收到的值赋值给工作内存中的变量,每当虚拟机遇到一个需要给变量赋值的字节码指令时执行该步操作。
  • store(存储):将工作内存中的变量值传送到主内存中,以便后续的write操作使用。
  • write(写入):将完成store操作的变量值写入到主内存的变量中。

同时在Java内存模型中明确规定了要执行这些操作需要满足以下规则:

  • 不允许read和load、store和write的操作单独出现。
  • 不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
  • 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
  • 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
  • 一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现
  • 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值
  • 如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
  • 对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

 

 

 



所属网站分类: 技术文章 > 博客

作者:码神

链接:http://www.javaheidong.com/blog/article/207498/7abfc43f8fb8996737ff/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

8 0
收藏该文
已收藏

评论内容:(最多支持255个字符)