导图社区 Java内存模型The Java The Memory Model
java 内存模型JVM 及 JMM理解,JVM是Java程序运行的基础,它负责加载、解释和执行Java字节码。JVM是一个跨平台的抽象计算机,它隐藏了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
社区模板帮助中心,点此进入>>
互联网9大思维
组织架构-单商户商城webAPP 思维导图。
域控上线
python思维导图
css
CSS
计算机操作系统思维导图
计算机组成原理
IMX6UL(A7)
考试学情分析系统
Java内存模型The Java The Memory Model(JMM)
并发编程模型分类
并发编程中两个关键问题
线程之间如何通信
通信是指线程以何种机制交换信息。
线程之间如何同步
同步是指程序用于控制不同线程之间操作发生相对顺序的机制。
命令行编程中解决并发问题的两种模型
共享内存
通信:通过共享程序的公共状态进行隐式通信。
同步:显示进行同步,程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。
消息传递
通信:通过明确的发送消息来进行显式通信。
同步:由于消息的发送必须在接收之前,因此同步是隐式进行的。
Java并发采用的模型
共享内存模型
隐式通信,不了解机制,会出现很多内存可见性问题。
JMM与JVM
JMM模型描述的java并发编程的内存规范,JVM描述的是java虚拟机的内存组织方式。
JVM内存模型
程序计数器(Program Counter Register)
当前线程所执行的字节码的行号指示器,字节码解
Java 堆(Java Heap)
Java 虚拟机中内存大的一块,是被所有线程共享 的,几乎所有的对象实例都在这里分配内存;
Java 虚拟机栈(Java Virtual Machine Stacks)
用于存储局部变量表、操作 数栈、动态链接、方法出口等信息;
本地方法栈(Native Method Stack)
与虚拟机栈的作用是一样的,只不过虚 拟机栈是服务 Java方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
方法区(Methed Area):
用于存储已被虚拟机加载的类信息、常量、静态变 量、即时编译后的代码等数据
从以上可以得出结论,JMM控制的共享变量之间的可见性对应JVM内存的堆区和方法区
并发问题产生的原因
重排序,可能会导致多线程出现内存可见性问题
编译器重排序
编译器在不改变单线程程序语义的情况下,可以重新安排语句的重排序
处理器重排序
指令级的重排序
现代处理器采用了指令级并行技术(Instruction-Level Parallelism)来将多条指令重叠执行。不过不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
内存系统的重排序。
由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
JMM内存可见的保证
java源代码到最终执行的指令序列经历的排序
源代码-->1:编译器优化重排序-->2:执行级并行重排序-->3:内存系统重排序-->4:最终执行的指令序列
常见处理器允许的重排序类型的列表
"N"表示处理器不允许两个操作重排序,“Y”表示允许重排序,sparc-TSO是指以TSO(Total Store Order )内存模型运行时,sparc处理器的特性。下表中的x86处理器包括x64及amd64。ARM处理器的内存模型与Power PC处理器的内存模型非常类似。
数据依赖性:如果两个操作访问同一个变量,且这两个操作有一个为写操作,此时这两个操作存在数据依赖性。这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作。
JMM处理重排序手段
JMM编译器重排序的处理规则
禁止特定类型的编译器重排序
处理器的重排序处理规则
java编译器生成指令序列时,插入特定类型的内存屏障(memory barriers ,intel 称之为 memory fence),通过内存屏障指令来禁止特定类型的处理器重排序。
内存屏障分类
JDK5开始,使用JSR-133内存模型,使用happens-before概念阐述操作之间的内存可见性。
定义
如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见。并不意味着,前一个操作必须要在后一个操作之前执行。仅仅要求前一个操作(执行结果)对一后一个操作可见,且前一个操作按顺序排在第二个操作之前(the first is visible to and ordered before the second )
happens-before规则
程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
监视器锁规则:对于一个监视器的解锁,happens-before于随后对这个监视器的加锁
volatile变量规则:对于一个volatile域的写,happens-before于任意后续对这个volatile域的读
传递性:如果A happens-before B,且B happens-before C,那么A happens-before C
as-if-serial语义
不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,runtime和处理器都必须最后as-if-serial语义。因此对不会对存在数据依赖关系的操作做重排序。
锁
CAS
volatile变量的原子操作记录状态值,共享锁状态
concurrent包
Monitor
JMM设计
两个关键因素
程序员对内存模型的使用
程序员希望内存模型易于理解,易于编程。程序员希望基于一个强内存模型来编写代码。
编译器和处理器对内存模型的实现
编译器和处理器希望内存模型对它们的束缚越少越好,这样它们就可以做更多的优化来提高性能,编译器希望实现一个弱内存模型。
只要不改变程序的执行结果(单线程和正确同步的多线程),编译器和处理器怎么优化都行。