Java内存模型学习

简介: 1,内存模型 左侧绿色区域为共享内存区,右侧黄色区域为线程私有内存区①方法区:存放被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码,方法区有一个运行时常量池存放编译器生成的字面量和符号引用。

1,内存模型
image

左侧绿色区域为共享内存区,右侧黄色区域为线程私有内存区
①方法区:存放被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码,方法区有一个运行时常量池存放编译器生成的字面量和符号引用。
②堆:虚拟机启动时创建,Java虚拟机管理内存中最大的一块,用于存放对象实例(注意:因为堆是垃圾收集器管理的主要区域,因此也叫GC堆)
③程序计数器:记录当前线程执行的字节码行号指示器,控制分支,循环,跳转,异常,线程恢复等基础功能
④虚拟机栈:虚拟机私有,线程创建时创建,代表java方法执行的内存模型。每个方法执行都会创建一个栈帧来存储方法的变量,操作数栈,动态链接方法,返回值,返回地址等信息。每个方法从调用到结束就对应于虚拟机栈中入栈和出栈的过程。
⑤本地方法栈:与虚拟机用到的Native方法相关。

2,内存执行模型
java程序的运行实体是线程,每个线程都会有一个工作内存(即栈空间)由线程私有,而内存模型归档所有的变量都存储在所有线程共享的堆内存,所以线程对变量的操作要:
①从堆内存中拷贝变量的副本到本线程的工作内存中
②在本线程的工作内存中操作变量副本
③操作完成后将变量写会回主内存
注意:如果方法中有一个局部变量是基本数据类型(如int, long, boolean, byte, short, char, float, double)则该变量直接存储在线程私有的栈内存中,如果本地变量是引用类型,则该引用存储在栈内存中,引用指向的实例存放在堆内存中。

3,CPU与内存的交互模型
image

读写速度CPU寄存器>CPU缓存>RAM

4,java线程与内核线程
内核线程是操作系统内核支持的线程,由操作系统内核完成线程管理,对于应用程序而言,一般不会直接调用内核线程,而是使用一种轻量级的进程(即通称意义上的线程),每个轻量级的进程都会映射到一个内核线程上,然后由操作系统将内核线程分发给各个处理器处理。
一个轻量级进程(线程)会映射到一个内核线程

image

5,线程安全问题
1)多个线程同时操作堆内存中的数据(线程间共享)时,可能引发线程安全问题,原因是:每个线程都会拷贝一份数据副本到线程私有内存区,如果线程A,B同一时间段内读取数据,修改,并回写,可能发生①A回写前,B就复制副本;②A回写后,B才复制副本等不确定问题。
2)程序运算的时候并不是所有操作在操作系统层都是原子性的,例如程序执行c = a+b,在指令层面可能会有:①load a to register1②load b to register2③add register1 register2 to register3④load register3 to c。这样的情况如果在多线程同时处理c变量的时候就有可能出现线程安全问题。另外:编译器语句重排;执行并行重排;内存系统重排等。
3)线程A修改了共享变量a的值,还未回写到共享存储区之前线程B是不知道修改后的值的,但在单线程下,修改后的值都是可见的,这叫可见性
4)java程序中,在本线程内所有的操作都视为有序的,这叫有序性;多线程环境下,一个线程中观察另外一个线程,所有操作都是无序的(由于指令重排/主内存和工作内存的延迟同步现象)

6,如何解决上面的原子性,可见性,有序性
①synchronized或ReentrantLock保证操作的原子性(volatile不能保证原子性)
②synchronized或volatile关键字保证可见性
③volatile保证有序性,因为它禁止重排优化
④happens-before原则

7,volatile的作用
①保证被volatile修饰的共享变量对所有的线程都是可见的,即:某个线程修改后的新值总是被其他线程立即得到
②禁止指令重排
volatile不能保证原子性,例如下面的程序可能会有线程安全问题
public class VolatileVisibility{
public volatile static int I = 0;
public static void increase(){

i++;//改操作不是原子性的,所以任然可能会有线程安全问题

}
}
修改方法是在increase方法上用synchronized修饰,属性定义上可去掉volatile修饰。
volatile保证可见性的方式:当修改一个volatile变量时,会强制将工作内存中改变后的值刷新到主内存;读取volatile变量时,会先将本线程工作内存中的值置为无效,重新从主内存里读取新副本。
④典型单例模式中禁止重排例子
Public class DoubleCheckLock {
private static DoubleCheckLock instance;
private DoubleCheckLock (){};
public DoubleCheckLock getInstance(){

if(null == instance){
    synchronized (DoubleCheckLock.class){
if(null == instance){
instance = new DoubleCheckLock();

}
}
}
return instance;
}
}
上面的程序有线程安全问题:当线程B读取到instance不为空的时候,其他线程初始化的动作可能还没有完成,因为new DoubleCheckLock();大致可以分为如下3步:
①memory = allocate();//分配内存空间
②instance(memory);//初始化内存区域
③instance=memory;//将初始化好的内存区域赋值给instance
上面三步中的②③可能会出现重排,即先赋值,再初始化。因此此时应该在私有变量instance上用volatile修饰:
public volatile static DoubleCheckLock instance;

目录
相关文章
|
16天前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
29 6
|
7天前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
15 0
|
18天前
|
存储 算法 Java
Java内存管理深度剖析与优化策略####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,重点分析了堆内存的分配策略、垃圾回收算法以及如何通过调优提升应用性能。通过案例驱动的方式,揭示了常见内存泄漏的根源与解决策略,旨在为开发者提供实用的内存管理技巧,确保应用程序既高效又稳定地运行。 ####
|
9天前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
23 8
|
7天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
11天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
40 5
|
9天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
9天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
14天前
|
算法 Java 开发者
Java内存管理与垃圾回收机制深度剖析####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,特别是其垃圾回收机制的工作原理、算法及实践优化策略。不同于传统的摘要概述,本文将以一个虚拟的“城市环卫系统”为比喻,生动形象地揭示Java内存管理的奥秘,旨在帮助开发者更好地理解并调优Java应用的性能。 ####
|
15天前
|
Java
java内存区域
1)栈内存:保存所有的对象名称 2)堆内存:保存每个对象的具体属性 3)全局数据区:保存static类型的属性 4)全局代码区:保存所有的方法定义
20 1