jvm内存模型和java内存模型

初识java虚拟机,就碰到一系列不懂的问题。我们以前常说java把局部变量放在栈里,new出来的变量放在堆里,然后堆里的数据不定时就给回收了。然后,如果是多线程的话,每个线程自己都有会一个私有的虚拟机栈,运行每个方法时都会创建一个栈帧,栈帧里存储着局部变量啦等信息,方法结束栈帧就出栈。这好像就是我们对java内存模型的第一次理解吧。直至今天,我看了java线程通讯之java内存模型,出现了主内存、工作内存等相关的字眼,说什么工作内存从主内存拷贝一份共享变量做高速缓存,每个线程拥有一个工作内存,这什么内存模型,又解决了什么问题呢。甚是不解,搜索了半天。原来一开始我们就搞混乱了。我们之前说的栈堆那个是JVM内存模型啊。

区别:JVM内存模型则是指JVM的内存分区,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途。

我们可以看到,Java堆和方法区的区域是多个线程共享的数据区域。也就是说,多个线程可以操作保存在堆或者方法区中的同一个数据。这也就是我们常说的“Java的线程间通过共享内存进行通信”。那么java虚拟机从底层就怎么操作的呢。

JMM并不像JVM内存结构一样是真实存在的,只是一个抽象的概念。JMM是和多线程相关的,描述了一组规则或规范,这个规范定义了一个线程对共享变量的写入时对另一个线程是可见的。简单总结下,Java的多线程之间是通过共享内存进行通信的,而由于采用共享内存进行通信,在通信过程中会存在一系列如可见性、原子性、顺序性等问题,而JMM就是围绕着多线程通信以及与其相关的一系列特性而建立的模型。JMM定义了一些语法集,这些语法集映射到Java语言中就是volatile、synchronized等关键字。所以,我理解的就是JMM就是为了解决Java多线程对共享数据的读写一致性问题而产生的一种模型!

下图是反映了主内存与线程工作内存(即是本地内存)之间的关系:

JMM的主要目标是实现在JVM中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程里面的变量有所不同步,它包含了实例字段、静态字段和构成数组对象的元素,但不包含局部变量和方法参数,因为后者是线程私有的,不会共享,当然不存在数据竞争问题。所以,我理解的是上图中的共享变量只是堆中的部分变量。而JMM规定了所有的变量都存储在主内存中,这个变量我想都是堆变量,如果硬是要跟JVM做一下匹配,那么我想主内存就相当于堆内存和方法区。然后线程copy的共享变量只是对部分堆变量的copy。那么,可想而知,如果硬是要匹配,我想工作内存里是包含两部分:线程私有的栈(这里不共享,也就没啥事),对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓冲区)。

看张图就清晰了,

每个线程都有自己的工作内存,工作内存中保存的是主存中某些变量的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。线程之间无法直接访问对方的工作内存中的变量,线程间变量的传递均需要通过主内存来完成。

分析上图:

1.线程A把从工作内存更新过的共享变量刷新到主内存中去。

2.线程B到主内存中去读取线程A刷新过的共享变量,然后copy一份到自己的工作内存里去。

虽然是这样,并没有解决并发问题啊,不可见?不具备原子性。这时候JMM定义了一些语法集,就是volatile、synchronized啦。

例如可见性吧,一个线程对共享变量做了修改之后,其他的线程立即能够看到该变量这种变化。Java内存模型是对共享变量进行volatile修饰,然后一个线程通过将在工作内存中的变量修改后的值同步到主内存,另一个线程会立马会看到变化,然后从主内存刷新最新值到工作内存中,这种依赖主内存的方式来实现可见性的。

总之,JVM内存模型是真的内存结构管理,Java内存模型只是为了适应和解决多线程通信而产生的一种模型,通过一些关键字修饰就可以实现并发。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值