首页 > 编程知识 正文

java对象内存模型,java虚拟机内存模型

时间:2023-05-05 13:12:52 阅读:14730 作者:1600

简介:

Java线程之间的通信对程序员完全透明,内存可见性问题容易困扰Java程序员。 这一系列文章揭开了Java内存模型的神秘面纱。 这一系列文章大致可分为四个部分,分别如下。

http://www.Sina.com/http://www.Sina.com/http://www.Sina.com /一、Java内存模型基础1.1并发编程模型中的在命令型编程中,线程间的通信机构有共享内存和消息传递两种。

在3358 www.Sina.com/http://www.Sina.com/http://www.Sina.com/——程序中,用于控制不同线程按键操作的相对顺序的机制。

共享内存:同步是显式进行的。 程序员必须显式指定方法或代码的一部分,因此必须在线程之间互斥地执行消息传递。 同步是隐式进行的。 因为发送消息必须在接收消息之前。 3358 www.Sina.com/http://www.Sina.com/http://www.Sina.com /

1.2 Java内存模型抽象结构Java中的所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享(文章称为“共享变量”)。 局部变量、方法定义参数和异常处理程序参数不在线程之间共享

Java线程之间的通信由Java内存模型(JMM )控制,JMM确定一个线程向共享变量的写入操作何时显示在另一个线程上。 抽象地看,JMM定义了线程和主内存之间的抽象关系。 线程之间的共享变量存储在主内存中,每个线程都有专用的“局部内存”(Local Memory ),而局部内存存储该线程以读写共享变量的副本。 对于本地内存,JMM的抽象概念是不存在的。 JMM包括缓存、写缓冲区、寄存器以及其他硬件和编译器优化。

Java内存模型基础,主要介绍内存模型相关基本概念

Java内存模型中的顺序一致性,主要介绍重排序与顺序一致性内存模型

从上图可见,线程a和线程b之间的通信需要经过以下两个步骤:

线程a将在本地内存a中更新的变量刷新为主内存的线程b,并将在线程a之前更新的共享变量读取到主内存中

同步原语,主要介绍三个同步原语(synchronized、volatile和final)的内存语义及重排序规则在处理器中的实现上图所示,本地内存a和本地内存b都有主内存中共享变量x的副本。 初始情况下,假设这三个内存中的x值都为0。 线程a在运行时,将更新的x值(假设值为1 )临时存储在其本地存储器a中。 线程a和线程b需要通信是因为线程a首先将位于其本地存储器中的修改后的x刷新到主存储器中,此时主存储器中的x值变为1。 然后,线程b去主存储器读取线程a更新后的x的值,此时线程b的本地存储器x的值也被更新为1。

总的来说,这两个步骤实际上是线程a向线程b发送消息,该通信过程必须通过主存储器。 http://www.Sina.com/http://www.Sina.com /

1.3当运行源代码到指令的排序程序时,编译器和处理器往往会对指令进行排序以提高性能。 有三种类型的排序。

编译器优化排序。 编译器可以在不改变单线程程序语义的情况下改变语句的执行顺序。 指令级并行排序。 现代处理器采用ILP (instruction-level parallelism,ILP ),重叠执行跳转指令。 在不依赖数据的情况下,处理器可以改变语句对应和该指令的执行顺序。 内存系统排序。 由于处理器使用缓存和读/写缓冲区,加载和保存操作可能会看起来不正常。 Java源代码的最终实际执行指令序列分别经历以下三种类型的排序: 其中,1是编译器排序,2和3是处理器排序。Java内存模型的设计,主要介绍Java内存模型的设计原理,及其与处理器内存模型和顺序一致性内存模型的关系。

通信

>重排序可能会导致多线程程序出现内存可见性问题,对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序(不是所有的编译器重排序都需要禁止)。对于处理器重排序,JMM的处理器重排序规则会要求Java编译器在生成指令序列时,插入特定类型的内存屏障(Memory Barries, Intel称之为Memory Fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序。
JMM属于语言级的内存模型,它确保在不同的编译器和不同的处理器平台之上,通过禁止特定类型的编译器重排序和处理器重排序,为程序员提供一致的内存可见性保障。

1.4 写缓冲区和内存屏障 1.4.1 写缓冲区

现代处理器都会使用写缓冲区临时保存向内存中写入的数据。写缓冲区的主要作用:

可以保证指令流水线持续运行,可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟。它以批处理的方式方式刷新写缓冲区,以及合并写缓冲区中对统一地址的多次写,减少对内存总线的占用。

常见处理器允许的重排序类型(Y-表示允许两个操作重排序,N-表示处理器不允许两个操作重排序)

处理器规则Load-LoadLoad-StoreStore-StoreStore-Load数据依赖性SPARC-TSONNNYNx86NNNYNIA64YYYYNPowerPCYYYYN

说明:常见处理器都允许Store-Load重排序;常见的处理器都不允许对存在数据依赖性的操作做重排序。N多的表示处理器拥有相对较强的处理器内存模型。

由于写缓冲器仅仅只对它所在的处理器可见,这个特性会对内存操作的执行顺序产生非常重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致。
举例说明:

示例处理器ProcessorAProcessorB初始a=0b=0伪代码a=1; //A1
x=b;//A2b=2; //B1
y=a;//B2运行结果x=y=0x=y=0

假设处理器A和处理器B按程序的顺序并行执行内存访问,最终可能得到x=y=0的结果,具体原因如下:

处理器和内存交互示意图

说明:处理器A和处理器B可以同时把共享变量写入自己的写缓冲区(A1、B1),然后从内存中读取另一个共享变量(A2、B2),最后才把自己写缓冲区中保存的脏数据刷新到内存中(A3、B3)。当以这种时序执行时,程序就可以得到x=y=0结果。

1.4.2 内存屏障

为了保证内存可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。JMM把内存屏障指令分为4类:

屏障类型指令示例说明LoadLoad BarriersLoad1;LoadLoad;Load2确保Load1数据的装载先于Load2及所有后续装载指令的装载StoreStore BarriersStore1;StoreStore;Store2确保Store1数据对其他处理器可见(刷新到主内存)先于Store2及所有后续存储指令的存储LoadStore BarriersLoad1;LoadStore;Store2确保Load1数据装载先于Store2及后续的存储指令刷新到内存StoreLoad BarriersStore1;StoreLoad;Load2确保Store1数据对其他处理器变得可见(指刷新到主内存)先于Load2及所有后续装载指令的装载。StoreLoad Barriers会使该屏障之前的所有内存访问指令(存储和装载指令)完成之后,才执行屏障之后的内存访问指令。

StoreLoad Barriers是一个“全能型屏障”,它同时具有其它3个屏障的效果。现代大多数处理器支持该屏障(其他类型的屏障不一定被所有处理器支持)。执行该屏障开销会很昂贵,因为处理器需要把缓冲区的内容全部刷新到内存中(Buffer Fully Flush)。

1.5 happens-before 简介

从JDK1.5开始,Java使用新的JSR-133内存模型。JSR-133使用happens-before的概念来阐述操作之间的内存可见性。在JMM中,如果一个操作的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。这里的两个操作可以是单线程也可以是多线程。
happens-before规则:

程序顺序规则:一个线程中的每个操作,happens-before于该线程的任意后续操作。监视器锁规则:对于一个锁的解锁,happens-before于随后对这个锁的加锁。volatile变量规则:对于一个volitale域的写,happens-before于任意后续对这个volatile域的读。传递性:如果A happens-before B,且B happens-before C ,那么A happens-before C。

注意:
两个操作之间具有happens-before关系,并不意味着前一个操作必须在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前(the first is visiable to and ordered beofre the second)。

图示happens-before与JMM的关系

happens-before与JMM的关系
一个happens-before规则对应于一个或多个编译器个处理器重排序规则。对于Java程序员来说,happens-before规则简单易懂,它避免了Java程序员为了理解JMM提供的内存可见性保证而去学习复杂的重排序规则以及这些规则的具体实现方法。

文章总结至《Java并发编程艺术》,下篇总结“重排序”,敬请关注。

有经典,有干货,微信搜索【kldbd】关注这个傻瓜式坚持的程序员。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。