Java千百问_07JVM架构(001)_java内存模型是什么样的

点击进入_更多_Java千百问

1、什么是内存模型

  Java平台自动集成了线程以及多处理器技术,这种集成程度比Java以前诞生的计算机语言要厉害很多。Java针对多种异构平台的独立性,使得多线程技术也具有了开拓性的一面。

  我们有时候在Java开发中,对于同步和线程安全要求很严格的程序时,往往容易混淆的一个概念就是内存模型。那究竟什么是内存模型呢?

  内存模型描述了程序中各个变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存、从内存中取出变量这样的底层细节。

  Java对象最终是存储在内存里面的,这点没错,但是编译器、运行库、处理器或者系统缓存有权指定内存位置来存储或者取出变量的值。

2、内存模型有哪些规则

内存模型需要具有以下规则:原子性(Atomicity)、可见性(Visibility)、可排序性(Ordering)

1. 原子性(Atomicity)

原子性指的是原子级别的操作,比如最小的一块内存的读写操作,可以理解为Java语言编译过后最接近内存的最底层的操作单元。这种读写操作的数据单元不是变量的值,而是本机码。

原子性规则约定了:访问存储单元内任何类型字段的值以及对其更新操作时,除了long类型和double类型,其他类型的字段是必须要保证其原子性的,这些字段也包括为对象服务的引用。即,如果你获得或者初始化某一些值时(这些值是由其他线程写入的,而且不是从两个或者多个线程在同一时间戳混合写入的),该值的原子性在JVM内部是必须得到保证的。

此外,原子性扩展规则可以延伸到基于long和double的另外两种类型:volatile long和volatile double(volatile为java关键字),没有被volatile声明的long类型以及double类型的字段值虽然不保证其JMM中的原子性,但是是被允许的。

只要在不违反该规则的情况下,JVM并不关心数据的值来自什么线程,正这样使得Java语言在并行运算的设计中,针对多线程的原子性设计变得极其简单。即使开发人员没有考虑到,最终的程序也没有太大的影响。

2. 可见性(Visibility)

可见性指的是一个线程修改的状态对另一个线程是可见的。也就是说一个线程修改的结果,另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存,所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作a++;这个变量a具有可见性,但是a++依然是一个非原子操作,也就这这个操作同样存在线程安全问题。

在可见性规则的约束下,定义了一个线程在哪种情况下可以访问或者影响另外一个线程,以及从另外一个线程的可见区域读取相关数据、将数据写入到另外一个线程内。

3. 可排序性(Ordering)

可排序性是指为了提高性能,编译器和处理器可能会对指令做重排序,包括:

  • 编译器优化的重排序

    编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

  • 指令级并行的重排序

    现代处理器采用了指令级并行技术(Instruction-LevelParallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

  • 内存系统的重排序

    由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

volatile修饰的变量不允许线程内部缓存和重排序。

可排序性规则将会约束任何一个违背了规则调用的线程在操作过程中的一些顺序,排序问题主要围绕了读取、写入和赋值语句有关的序列。

3、Java内存模型是什么

JMM(Java内存模型,Java Memory Model的缩写)是控制Java线程之间、线程和主存之间通信的协议。

JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

??JMM结构如下:

时间: 2024-10-10 12:32:46

Java千百问_07JVM架构(001)_java内存模型是什么样的的相关文章

Java千百问_07JVM架构(016)_java内存如何优化

点击进入_更多_Java千百问 1.java内存如何优化 了解jvm内存管理看这里:jvm是如何管理内存的 了解堆内存看这里:java堆内存是什么样的 java内存的优化主要是通过合理的控制GC来实现,主要原则: 1. 不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况(因为GC过后这个值是不会变化的). 2. 使用JDK提供的内存查看工具,比如JConsole和Java VisualVM. 3. 优化内存主要的目的是降低youngGC的频率.减少fullG

Java千百问_07JVM架构(011)_java垃圾回收都有哪些方式

点击进入_更多_Java千百问 1.java垃圾回收都有哪些方式 所谓垃圾回收方式,是指JVM提供的几种不同的垃圾回收器,不同的垃圾回收器进行垃圾回收时采用不同的方式.当然,总体原则遵循java垃圾回收机制. 了解java内存模型看这里:java内存模型是什么样的 了解堆内存看这里:java堆内存是什么样的 了解java垃圾回收机制看这里:java垃圾回收机制是什么 每种方式都有自己的优势与劣势.我们编程的时候可以通过向JVM传递参数来选择垃圾回收器.不同的垃圾回收期有大的不同,可以为我们提供完

Java千百问_07JVM架构(013)_java什么情况会内存溢出

点击进入_更多_Java千百问 1.Java堆什么情况会溢出 所有对象的实例都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,如果程序使用的内存超过了堆最大内存(-Xmx),则会溢出Java heap space. 了解java内存模型看这里:java内存模型是什么样的 了解堆内存看这里:java堆内存是什么样的 了解java垃圾回收机制看这里:java垃圾回收机制是什么 实例: public class HeapOOM { static class OOMObject{} /** *

Java千百问_07JVM架构(008)_java垃圾回收机制是什么

点击进入_更多_Java千百问 1.如何判断垃圾对象 垃圾收集的第一步就是先需要算法来标记哪些是垃圾,然后再对垃圾进行处理.通常的编程语言都会用以下算法之一进行判断: 引用计数(ReferenceCounting)算法 这种方法比较简单直观,核心思路是,给每个对象添加一个被引用计数器,被引用时+1,引用失效-1,等于0时就表示该对象没有被引用,可以被回收. FlashPlayer/Python使用该算法,简单高效.但是,Java/C#并不采用该算法,因为该算法没有解决对象相互引用的问题,即:当两

Java千百问_07JVM架构(006)_java堆和栈有什么区别

点击进入_更多_Java千百问 1.java堆和栈有什么区别 了解jvm内存管理看这里:jvm是如何管理内存的 在<jvm是如何管理内存的>这篇文章中,已经对PC寄存器(计数器 pc registers).方法区(method area).本地方法栈(native method stacks).栈(stacks).堆(heap)内存区域做了介绍,其中栈(stacks).堆(heap)是java内存管理中非常重要的两个部分,具体区别如下: 2.基本数据类型储存在栈中吗 基本数据类型由于长度固定,

Java千百问_07JVM架构(018)_如何监控jvm的运行情况

点击进入_更多_Java千百问 1.如何监控jvm的运行情况 了解jvm内存模型看这里:java内存模型是什么样的 了解jvm内存管理看这里:jvm是如何管理内存的 了解jvm垃圾回收机制看这里:java垃圾回收机制是什么 了解jvm内存优化看这里:java内存如何优化 我们通常使用Jdk工具来监控jvm的运行情况,当然目前有很多第三方产品是通过jdk提供的api来组织数据进行监控的.具体来说有如下监控软件: Jconsole jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回

Java千百问_07JVM架构(002)_jvm实例的结构是什么样的

点击进入_更多_Java千百问 1.jvm实例的结构是什么样的 在Java虚拟机规范中,一个虚拟机实例的行为主要组成部分为:子系统.内存区域.数据类型和指令. 这些组件描述了JVM内部的一个抽象结构.与其说这些组成部分的目的是进行JVM内部结构的一种支配,不如说是提供一种对外部行为的严格定义,该规范定义了这些抽象组成部分的相互作用,以及Java虚拟机执行所需要的行为. 了解jvm内存管理看这里:java内存模型是什么样的 下图描述了JVM实例的一个内部结构,其中主要包括主要的子系统.内存区域.

Java千百问_07JVM架构(012)_fullGC、minorGC、magorGC有什么区别

点击进入_更多_Java千百问 1.fullGC.minorGC.magorGC有什么区别 fullGC.minorGC.magorGC还有youngGC是Java垃圾处理机制(GC)的名词,区分这几个概念非常简单: 老生代进行一次垃圾清理,被称为fullGC或者magorGC. 新生代进行一次垃圾清理,被称为youngGC或者minorGC. 了解java垃圾回收机制看这里:java垃圾回收机制是什么 解释完毕,不过要提一下的是,我们在JVM优化过程中的一个原则就是: 降低youngGC的频率

Java千百问_07JVM架构(019)_运行时常量池是什么

点击进入_更多_Java千百问 1.运行时常量池是什么 运行时常量池(Runtime Constant Pool),它是方法区的一部分.Class文件中除了有类的版本.字段.方法.接口等描述等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到常量池中. 了解java内存管理看这里:jvm是如何管理内存的 如图: 运行时常量是相对于常量来说的,它具备一个重要特征是:动态性.当然,值相同的动态常量与我们通常说