当前位置: 首页 > article >正文

JAVA内存模型!=JVM内存模型

文章目录

  • 前言
  • JVM内存模型
  • JAVA内存模型
  • JAVA内存模型解释的问题
    • 可见性问题
    • 一致性问题
  • 总结

前言

有很多JAVA开发人员,在被问起:“你知道Java内存模型吗?”,都会回答:“知道,JAVA内存模型分为方法区、堆、…”。

虽说“概念”这个词发明出来是为了方便交流和说明问题的,不用太过于较真。但是,答非所问就是你的不对了。

如果对两者的概念混淆不清的,希望在看完本文后对你有所帮助。

JVM内存模型

先说什么是JVM内存模型,我相信99.99%的JAVA开发人员都知道,因为面试经常会被问到。。。

没错,就是方法区、堆、…

叫法也是五花八门,“JVM内存布局“、“JVM内存划分“又或是“JVM内存结构“,总有一个你听过的。

官方的叫法其实是“运行时数据区域”。这里是官方的说明:

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5

如果想快速了解的,可以移步至Java面试中经常被问到的15道JVM面试题,里面有JVM内存相关的面试题。

那JAVA内存模型又是什么呢?

JAVA内存模型

在了解Java内存模型之前,建议先对计算机存储器的层次结构有基本的了解,特别是缓存、主存以及它们之间的交互关系。

JAVA内存模型简称:JMM(Java Memory Model),分为主内存和工作内存。

  • 主内存是所有线程共享的区域,包含了所有共享变量、类信息、实例对象等,也就是运行时数据区域中的堆和方法区的数据。
  • 工作内存是每个线程在执行时的私有空间,包含了局部变量表、操作数栈等,也就是运行时数据区域中的程序计数器和栈的数据。

在这里插入图片描述

如果看过官方的文档,你会发现对内存模型的描述是在线程和锁的章节中,可见对其描述的目的。

感兴趣的可以去官方文档瞅一瞅

简而言之,JAVA内存模型解释了在多线程编程中对共享数据访问和修改会产生的一些问题和原因,以及如何解决这些问题。

下面一一说明。

JAVA内存模型解释的问题

可见性问题

先了解一下线程执行时主内存和工作内存是如何交互的:

线程在执行时,会将主内存中的数据复制到自己的工作内存中进行操作,操作完成后再将结果刷新回主内存。

为了提高性能,JVM和处理器会对此过程进行优化:尽量减少主内存和工作内存的数据交换次数。这就意味着两点:

  • 当线程需要访问一个共享变量时,不会每次都从主内存中读取,而是访问工作内存中已有的这个变量。
  • 当线程修改了共享变量的值时,可能不会立即写回主内存。

这时候就会存在一个问题,如下面的示例代码。

readerThread 可能会永远看不到flag被设置为true,因为它一直在自己的工作内存中查看flag的旧值。

这种“线程对变量的修改对其他线程不可见”,就是可见性问题。

为了解决可见性问题,JMM提供了 volatile 关键字。它会告诉JVM和硬件这个变量是易变的,不应该被优化。意味着两点:

  • 当线程需要访问一个 volatile 共享变量时,每次从主内存获取最新的值。
  • 当线程修改了 volatile 变量的值,该变量的新值会立即被同步到主内存。

在这里插入图片描述

​示例代码中的flagvolatile 修饰后,readerThread 会在flag更新后去主内存获取最新的值,然后继续向下执行。

一致性问题

JMM还解释了在多线程环境下,由于内存访问的并发性和编译器、处理器优化的影响,会发生数据不一致的问题。如:

  • 多线程在并发访问同一内存位置时,导致的数据不一致。

在这里插入图片描述

  • 一些非原子操作,例如i++,在多线程的环境下的的数据不一致。

在这里插入图片描述

  • CPU时间片轮转和指令重排序导致多线程环境下的数据不一致。

对于以上产生问题的几个场景,只要可以协调线程的执行顺序,确保结果是按照某种全局顺序执行的,就可以解决数据不一致的问题。

Java 开发人员都知道,通过同步机制可以保证这一点。

总结

虽然JAVA内存模型!=JVM内存模型,但两者也有一定的关联。

通过对JAVA内存模型的了解,能够对并发编程中存在的问题(可见性、原子性、有序性)有清晰的认识以及应对方案。


http://www.kler.cn/a/326111.html

相关文章:

  • 牛客题库 21738 牛牛与数组
  • Java基础-Java中的常用类(上)
  • 无人机动力系统测试-实测数据与CFD模拟仿真数据关联对比分析
  • 【设计模式】行为型模式(五):解释器模式、访问者模式、依赖注入
  • 另外一种缓冲式图片组件的用法
  • 【项目开发】URL中井号(#)的技术细节
  • UI设计师面试整理-工具和技术技能
  • 【大牛!】3DMAX城市交通插件CityTraffic使用方法详解
  • 关于vue2+uniapp+uview+vuex 私募基金项目小程序总结
  • 一文讲清CSS基础之浮动float原理
  • 关于宿主机功能正常docker容器重启后dns失效的解决办法
  • 江科大笔记—LED闪烁 LED流水灯 蜂鸣器
  • 每一个云手机的ip是独立的吗
  • .NET 6.0 使用log4net配置日志记录方法
  • electron教程(三)窗口设置
  • 微服务--Docker
  • 前端vue3中父div width: 40%; height: 62%; 子div如何设置相对父位置不变
  • 边缘计算网关:轻工行业的智能化新引擎
  • 数据权限的设计与实现系列11——前端筛选器组件Everright-filter集成功能完善2
  • 物业管理小程序开发
  • 微软SCCM:企业级系统管理的核心工具
  • 精密制造的革新:光谱共焦传感器与工业视觉相机的融合
  • JS设计模式之观察者模式:观察者与可观察对象的巧妙互动
  • 计算机毕业设计 基于Python国潮男装微博评论数据分析系统的设计与实现 Django+Vue 前后端分离 附源码 讲解 文档
  • 企业微信:客户联系自带群发工具和聊天工具
  • 【前端安全】burpsuite前端jsEncrypter插件详解