Java 内存模型与内存结构
Java内存模型
一、简介
Java内存模型(JMM)主要是为了规定线程和内存之间的一些关系;根据JMM的设计,系统存在一个主内存(Main Memory)和工作内存(Work Memory),Java中所有变量都储存在主内存中,对于所有线程都是共享的;每条线程都有自己的工作内存,工作内存中存储了该线程已读、写共享变量的副本,工作内存是JMM的一个抽象概念,主要包括:缓存,写缓冲区,寄存器以及其他的硬件和编译器优化;线程对所有变量的操作都是在工作内存中进行的,线程之间无法相互直接访问,变量传递均需要通过主内存完成。JMM示意图如下:
二、JMM带来了哪些问题?
1、可见性问题
CPU中运行的线程从主内存中拷贝共享对象obj到它的CPU缓存,把对象obj的count变量改为2,但这个变更对运行在右边CPU中的线程不可见,因为这个更改还没有flush到主内存中,要解决共享对象可见性这个问题,可以使用 volatile 或加锁(如:synchronized),来保证可见性。
2、竞争问题
线程A和线程B共享一个对象obj,假设线程A从主存读取Obj.count变量到自己的CPU缓存,同时,线程B也读取了Obj.count变量到自己的CPU缓存,并且这两个线程都对Obj.count做了加1操作;此时,Obj.count加1操作被执行了两次,不过都在不同的CPU缓存中,如果这两个加1操作是串行执行的,那么Obj.count变量便会在原始值上加2,最终主存中的Obj.count的值会是3;然而如果是并行操作,不管是线程A还是线程B先flush计算结果到主存,最终主内存中的Obj.count只会增加1次变成2;可以使用加锁( 如:synchronized) 解决此问题,来保证一致性。
3、重排序问题
在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。
可以使用volatile或加锁(如:synchronized)来保证有序性。
Java内存结构
先看一下结构图:
从图中可以看出Java内存结构包括五大区域:堆、方法区、虚拟机栈、本地方法栈、程序计数器,其中堆、方法区线程共享,虚拟机栈、本地方法栈、程序计数器线程私有。
1、堆
堆是Java虚拟机管理的最大一块内存区域,存放所有对象实例和数组,因为堆存放的对象是线程共享的,所以多线程的时候需要同步机制;堆又划分为:年轻代、老年代、永久代(JDK1.7)/元空间(JDK1.8),元空间与永久代的区别在于:永久代使用的是虚拟机内存,元空间则采用本地内存。
2、虚拟机栈
虚拟机栈描述的是线程进栈出栈的过程,线程结束内存自动释放,它用来存储当前线程运行方法所需要的数据、指令、返回地址(即局部变量和正在调用的方法),方法被调用时会在栈中开辟一块叫栈帧的空间,方法运行在栈帧空间中。
3、本地方法栈
本地方法栈与虚拟机栈的作用十分相似,区别是虚拟机栈执行的是Java方法服务,而本地方法栈则为虚拟机使用native方法服务,可能底层调用的c或者c++方法。
4、方法区
方法区同堆一样,是所有线程共享的内存区域,又被称为非堆,用于存储已被虚拟机加载的类信息、常量、静态变量等。
5、程序计数器
程序计数器是一块很小的内存空间,它是线程私有的,可以认作是当前线程的行号指示器。
参考:
[1] https://www.jianshu.com/p/8a58d8335270
[2] https://www.jianshu.com/p/de097e7a813a
[3] http://tutorials.jenkov.com/java-concurrency/java-memory-model.html
Java 内存模型与内存结构的更多相关文章
- java内存模型和内存结构
java内存模型说的是多线程,网上可能会有写误导,并不是什么堆.栈.方法区,很多人都会搞混.说白了就是多线程中主线程和本地线程之间的一个数据可见性问题. jmm:java内存模型:jvm:java内存 ...
- java并发学习--第十章 java内存模型的内存语义
一.锁的内存语义 所为的java内存模型的内存语义指的就是在JVM中的实现原则. 锁的内存语义:锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 我们把上面这句话再整理下: ...
- JVM并发机制的探讨——内存模型、内存可见性和指令重排序
并发本来就是个有意思的问题,尤其是现在又流行这么一句话:“高帅富加机器,穷矮搓搞优化”. 从这句话可以看到,无论是高帅富还是穷矮搓都需要深入理解并发编程,高帅富加多了机器,需要协调多台机器或者多个CP ...
- jvm内存模型-和内存分配以及jdk、jre、jvm是什么关系(阿里,美团,京东)
参考:JVM的垃圾回收机制 总结(垃圾收集.回收算法.垃圾回收器) 1.什么是jvm?(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的.(2) ...
- Java内存模型与内存结构
Java内存模型 一.简介 Java内存模型(JMM)主要是为了规定线程和内存之间的一些关系:根据JMM的设计,系统存在一个主内存(Main Memory)和工作内存(Work Memory),Jav ...
- JAVA高级篇(二、JVM内存模型、内存管理之第一篇)
JVM内存结构如 Java堆(Heap),是Java虚拟机所管理的内存中最大的一块.Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例,几乎所有的对象实 ...
- 【深入Java虚拟机】之一:Java内存模型与内存溢出
[深入Java虚拟机]之:Java内存区域与内存溢出 高速缓存模型如下: ----------------------------------------------------分割线-------- ...
- java内存模型,内存区域
Java虚拟机内存区域总结:Java虚拟机相当于一个抽象的计算机操作系统, 其管理的内从区域大体上可以分为栈和堆,就像c或c++中对内存的分类一样, 但这样的分类对于Java虚拟机来说太过粗浅, 实际 ...
- jvm内存模型和内存分配
1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的. (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和 ...
随机推荐
- Redis的初识
简介 已经有了Membercache和各种数据库,Redis为什么会产生?Redis纯粹为应用而产生,它是一个高性能的key-value数据库.Redis的出现,很大程序补偿了Memcached这类k ...
- C#开发BIMFACE系列16 服务端API之获取模型数据1:查询满足条件的构件ID列表
系列目录 [已更新最新开发文章,点击查看详细] 源文件/模型转换完成之后,可以获取模型的具体数据.本篇介绍根据文件ID查询满足条件的构件ID列表. 请求地址:GET https://api.b ...
- html基础——下拉式菜单
一个网站能否让用户容易使用该网站往往是由菜单栏体现出来,因为它为网页的大多数页面提供功能入口.一个轻轻的点击以后,即可显示出菜单项,将网站的大部分页面和功能显示出来让用户清楚了解从而用户节约一定的时间 ...
- zookeeper集群部署问题排查记录
今天在三台虚拟机搭建zookeeper集群,一直连不通,然后进行了几个小时的斗争,做个记录. 具体部署方式网上有很多, 不在赘述.产生连接不同的问题主要有以下几个方面: 1.仔细检查配置文件. 是否有 ...
- 获取mysql自主生成的主键
一.sql语句 CREATE TABLE `testgeneratedkeys` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) ...
- Django--路由层、视图层、模版层
路由层: 路由匹配 url(正则表达式,视图函数内存地址) 只要正则匹配到了内容,就不再往下匹配,而是直接运行后面的视图函数 匹配首页) url(r'^&', home) 匹配尾页 url(r ...
- 【学习笔记】第二章 python安全编程基础---python爬虫基础(urllib)
一.爬虫基础 1.爬虫概念 网络爬虫(又称为网页蜘蛛),是一种按照一定的规则,自动地抓取万维网信息的程序或脚本.用爬虫最大的好出是批量且自动化得获取和处理信息.对于宏观或微观的情况都可以多一个侧面去了 ...
- springboot logback日志的使用
以下有两个使用,一个是简单使用,另一个是需要进行详细的配置再使用.首先给出源代码.可以直接使用 import org.slf4j.Logger;import org.slf4j.LoggerFacto ...
- ACM卡常数(各种玄学优化)
首先声明,本博文部分内容仅仅适用于ACM竞赛,并不适用于NOIP与OI竞赛,违规使用可能会遭竞赛处理,请慎重使用!遭遇任何情况都与本人无关哈=7= 我也不想搞得那么严肃的,但真的有些函数在NOIP与O ...
- response对响应的设置
1.response对象设置响应行状态码: protected void doGet(HttpServletRequest request, HttpServletResponse response) ...