Java内存模型(JMM)详解(1)

简介: Java内存模型(JMM)详解

一、为什么要有内存模型

  • 在现代多核处理器中,每个处理器都有自己的缓存,需要定期的与主内存进行协调。
  • 想要确保每个处理器在任意时刻知道其他处理器正在进行的工作,将需要很大的开销,且通常是没必要的。

1.1 硬件的效率与一致性

1、 由于计算机的存储设备与处理器的运算能力之间有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(cache)来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中没这样处理器就无需等待缓慢的内存读写了。


2、多个处理器运算任务都涉及同一块主存,需要一种协议可以保障数据的一致性,这类协议有MSI、MESI、MOSI及Dragon Protocol等。Java虚拟机内存模型中定义的内存访问操作与硬件的缓存访问操作是具有可比性的。


3、基于高速缓存的存储交互很好地解决了处理器与内存的速度矛盾,但是引入了一个新的问题:缓存一致性(Cache Coherence)。在多处理器系统中,每个处理器都有自己的高速缓存,而他们又共享同一主存,下面会介绍这个问题

屏幕快照 2022-05-10 下午1.42.57.png

二、CPU和缓存一致性

2.1 为什么需要CPU cache

因为CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。CPU往往需要重复处理相同的数据、重复执行相同的指令,如果这部分数据、指令CPU能在CPU缓存中找到,CPU就不需要从内存或硬盘中再读取数据、指令,从而减少了整机的响应时间,所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题(结构:cpu -> cache -> memory)


屏幕快照 2022-05-10 下午1.43.36.png

在程序执行的过程中就变成了:


当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU

进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高

速缓存中的数据刷新到主存当中。


在Intel官网上产品-处理器界面内对缓存的定义为:CPU高速缓存是处理器上的一个快速记忆区域。英特尔智能高速缓存(SmartCache)是指可让所有内核动态共享最后一级高速缓存的架构。这里就提及到了最后一级高速缓存的概念,即为CPU缓存中的L3(三级缓存),那么我们继续来解释一下什么叫三级缓存,分别又是指哪三级缓存。

屏幕快照 2022-05-10 下午1.43.47.png

2.2 三级缓存(L1、L2、L3)


三级缓存(L1一级缓存、L2二级缓存、L3三级缓存)都是集成在CPU内的缓存

它们的作用都是作为CPU与主内存之间的高速数据缓冲区

L1最靠近CPU核心,L2其次,L3再次

运行速度方面:L1最快、L2次快、L3最慢

容量大小方面:L1最小、L2较大、L3最大

CPU会先在最快的L1中寻找需要的数据,找不到再去找次快的L2,还找不到再去找L3,L3都没有那就只能去内存找了。

单核CPU只含有一套L1,L2,L3缓存;如果CPU含有多个核心,即多核CPU,则每个核心都含有一套L1(甚至和L2)缓存,而共享L3(或者和L2)缓存。

单CPU双核的缓存结构:

屏幕快照 2022-05-10 下午1.44.29.png

在单线程环境下,cpu核心的缓存只被一个线程访问。缓存独占,不会出现访问冲突等问题

在多线程场景下,在CPU和主存之间增加缓存,就可能存在缓存一致性问题,也就是说,在多核CPU中,每个核的自己的缓存中,关于同一个数据的缓存内容可能不一致,这也就是我们上面提到的缓存一致性的问题


屏幕快照 2022-05-10 下午1.44.34.png


2.3 乱序执行优化


从java源码到最终实际执行的指令序列,会经历下面3种重排序:

屏幕快照 2022-05-10 下午1.44.38.png


重排序的现象:


a=10,b=a 这一组 b依赖a,不会重排序

a=10,b=50 这一组 a和b 没有关系,那么就有可能被重排序执行 b=50,a=10

cpu和编译器为了提高程序的执行效率会按照一定的规则允许指令优化,不影响单线程程序执行结果,但是多线程就会影响程序结果

屏幕快照 2022-05-10 下午1.44.42.png

目录
相关文章
|
17天前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
21 0
|
20天前
|
存储 监控 算法
Java内存管理深度剖析:从垃圾收集到内存泄漏的全面指南####
本文深入探讨了Java虚拟机(JVM)中的内存管理机制,特别是垃圾收集(GC)的工作原理及其调优策略。不同于传统的摘要概述,本文将通过实际案例分析,揭示内存泄漏的根源与预防措施,为开发者提供实战中的优化建议,旨在帮助读者构建高效、稳定的Java应用。 ####
32 8
|
17天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
21天前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
48 5
|
19天前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
19天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
24天前
|
算法 Java 开发者
Java内存管理与垃圾回收机制深度剖析####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,特别是其垃圾回收机制的工作原理、算法及实践优化策略。不同于传统的摘要概述,本文将以一个虚拟的“城市环卫系统”为比喻,生动形象地揭示Java内存管理的奥秘,旨在帮助开发者更好地理解并调优Java应用的性能。 ####
|
16天前
|
存储 监控 算法
Java内存管理的艺术:深入理解垃圾回收机制####
本文将引领读者探索Java虚拟机(JVM)中垃圾回收的奥秘,解析其背后的算法原理,通过实例揭示调优策略,旨在提升Java开发者对内存管理能力的认知,优化应用程序性能。 ####
30 0
|
存储 缓存 安全
基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程
许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存、CPU、缓存等予以说明。实际上,在实际的Java开发工作中,仅仅了解并发编程的创建、启动、管理和通信等基本知识还是不够的。
3971 0
|
8天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
38 6