前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试java内存模型

面试java内存模型

作者头像
小土豆Yuki
发布2020-06-15 17:21:55
4230
发布2020-06-15 17:21:55
举报
文章被收录于专栏:洁癖是一只狗洁癖是一只狗

JAVA内存模型

今天我们讲一下java内存模型(JMM),JMM的问题在面试中经常被问到,我们今天就讲一下这道题.

在正式Java内存模型之前,先讲一下机器硬件CPU.

计算机的并发问题和虚拟机的情况有不少相似之处,我们知道所有的运算操作都是由CPU完成的.CPU指令就牵扯到了数据的操作,难免就会和主内存打交道,虽然CPU发展的性能越来越好,但还是受限于内存的访问速度,通常这种差异是千差万别的,极端情况甚至上万倍.

基于上面原因,便有了加入缓存(CPU Cache)的机制,CPU Cache 充当CPU 和主内存的缓冲,就有了下面的操作

  1. 将数据先放到缓存中
  2. CPU就可以直接拿缓存的数据计算处理
  3. 处理完之后就再放回主内存中

下面就是CPU的架构图

虽然这样解决速度的问题,但是也带来了另外一个问题,缓存一致性,举个例子如i++。

  1. 读取主内存的 i到CPU Cache中
  2. 对进行加一操作
  3. 将结果写到CPU Cache中
  4. 将数据刷新到主内存中。

i++在单线程不会有问题,但是多线程下就会有问题,假设i的初始值是0,两个线程本地都把i=0缓存到的CPU Cache中,然后都对i进行加一操作后,然后把他们放到主内存,就有可能存储的i还是1,这就是典型的缓存不一致.

这问题也有解决的办法,有两种:

  1. 通过总线加锁的方式
  2. 通过缓存一致性协议。

第一种是早期的解决办法, 他的原理就是一种悲观的实现,有多个CPU要和主内存交互的之前,都要和总线(数据总线,控制总线,地址总线)进行通信,总线只会允许一个CPU访问变量的主内存,这种效率太低,第二种,就是缓存一致性方式解决一致性问题,看一下的图,如下

缓存一致性最为出名的是Intel的MESI协议,保证了缓存使用中共享变量副本都是一致的,他的原理是:

  1. CPU 操作Cache中的数据
  2. 如果发现变量是共享变量,也就是说其他CPU中也有一个副本
  3. 那么当读取数据时,不做任何处理
  4. 如果是写操作,就是会让其他CPU的缓存失效,其他CPU就会从主内存再次获取。

理解了上面的内存,那对Java内存模型学习就很容易了,但是他们不是一个东西,我们先看一下Java内存模型是啥样子

java的内存模型决定了一个线程对共享变量的写入何时对其他线程可见,Java内存模型定义线程和主内存之间的抽象关系,具体如下

  1. 共享变量存储于主内存,每个线程都可以访问
  2. 每个线程都有私有的工作内存,或者成为本地内存
  3. 工作内存只存储线程对变量的副本
  4. 线程不能直接操作主内存,只有先操作工作内存之后,才能写入主内存
  5. 工作内存和java内存模型都是抽象的概念,他并不真实存在,他涵盖了缓存,集萃器,编译器优化以及硬件等等

我们再来看一个例子

如图,本地内存A,和本地内存B有主内存中共享变量的X的副本,初始时,这3个内存中的x都是0,线程A执行后,把更新的值,临时放到自己的本地内存A中,当线程A和线程B通讯时候,线程A首先会把自己本地内存修改的值,放到主内存中,此时,B的本地内存已经失效,线程B到主内存拿到的值就是线程A更新后的值,线程B的本地内存就会变成1。这一点和CPU和CPU Cache 关系非常相似。

切记,他们并不完全一样,比如计算机物理内存不会存在栈内存,堆内存的划分,无论是堆内存还是虚拟机栈内存都会对应到物理的主内存,当然也有一部分的数据有可能存入CPU Cache寄存器中。如下图

JMM是一种规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题,java中的许多关键字是使用java内存模型封装了底层给我们使用,如synchronized ,volatile,final.这里我们不展开讲解,有兴趣的可以自行学习。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档