提升--21---JMM(Java内存模型)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


JMM--Java Memory Model

JMM 定义

JMM 是Java内存模型(Java Memory Model),简称JMM。它本身只是一个抽象的概念,并不真实存在,它描述的是一种规则或规范,

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

JMM规则:

  1. JMM规定了所有的变量都存储在主内存(Main Memory)中。每个线程还有自己的工作内存(Working Memory)

  2. 线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。

  3. 不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。

全局描述。 在处理指令时,CPU会拉取数据,优先级是从L1到L2到L3,如果都没有,需要去主内存中拉取,JMM就是在CPU和主内存之间,来协调,保证可见、有序性等操作。

  • CPU核心,就是CPU核心(寄存器)
    缓存是CPU的缓存,CPU的缓存分为L1(线程独享),L2(内核独享),L3(多核共享)
  • JMM就是Java内存模型的核心,可见性,有序性都基于这实现。
  • 主内存JVM,就是你堆内存。

线程间通信的步骤:

首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。

然后,线程B到主内存中去读取线程A之前已更新过的共享变量。

本地内存A和B有主内存中共享变量x的副本。假设初始时,这三个内存中的x值都为0。

  1. 线程A在执行时,把更新后的x值(假设值为1)临时存放在自己的本地内存A中。
  2. 当线程A和线程B需要通信时(如何激发?--隐式),线程A首先会把自己本地内存中修改后的x值刷新到主内存中,此时主内存中的x值变为了1。
  3. 随后,线程B到主内存中去读取线程A更新后的x值,此时线程B的本地内存的x值也变为了1。

从整体来看,这两个步骤实质上是线程A在向线程B发送消息,而且这个通信过程必须要经过主内存。JMM通过控制主内存与每个线程的本地内存之间的交互,来为java程序员提供内存可见性保证。

JMM的三大特性:

Java内存模型是围绕着并发编程中原子性、可见性、有序性这三个特征来建立的,那我们依次看一下这三个特征:

原子性(Atomicity)

一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。

基本类型数据的访问大都是原子操作,long 和double类型的变量是64位,但是在32位JVM中,32位的JVM会将64位数据的读写操作分为2次32位的读写操作来进行,这就导致了long、double类型的变量在32位虚拟机中是非原子操作,数据有可能会被破坏,也就意味着多个线程在并发访问的时候是线程非安全的。

可见性:

一个线程对共享变量做了修改之后,其他的线程立即能够看到(感知到)该变量的这种修改(变化)。

Java内存模型是通过将在工作内存中的变量修改后的值同步到主内存,在读取变量前从主内存刷新最新值到工作内存中,这种依赖主内存的方式来实现可见性的。

有序性:

JMM中的八种内存操作:

为了支持 JMM,Java 定义了8种原子操作,用来控制主存与工作内存之间的交互:

  • read 读取:作用于主内存,将共享变量从主内存传送到线程的工作内存中。

  • load 载入:作用于工作内存,把 read 读取的值放到工作内存中的副本变量中。

  • store 存储:作用于工作内存,把工作内存中的变量传送到主内存中。

  • write 写入:作用于主内存,把从工作内存中 store 传送过来的值写到主内存的变量中。

  • use 使用:作用于工作内存,把工作内存的值传递给执行引擎,当虚拟机遇到一个需要使用这个变量的指令时,就会执行这个动作。

  • assign 赋值:作用于工作内存,把执行引擎获取到的值赋值给工作内存中的变量,当虚拟机栈遇到给变量赋值的指令时,就执行此操作。

  • lock锁定: 作用于主内存,把变量标记为线程独占状态。

  • unlock解锁: 作用于主内存,它将释放独占状态。

相关推荐
少许极端44 分钟前
算法奇妙屋(七)-字符串操作
java·开发语言·数据结构·算法·字符串操作
懒羊羊不懒@1 小时前
Java基础语法—字面量、变量详解、存储数据原理
java·开发语言
望获linux1 小时前
【实时Linux实战系列】实时 Linux 的自动化基准测试框架
java·大数据·linux·运维·网络·elasticsearch·搜索引擎
Code blocks1 小时前
GB28181视频服务wvp部署(一)
java·spring boot·后端
我命由我123451 小时前
Spring Boot - Spring Boot 静态资源延迟响应(使用拦截器、使用过滤器、使用 ResourceResolver)
java·spring boot·后端·spring·java-ee·intellij-idea·intellij idea
Xzh04231 小时前
前后端学习的交界
java·ajax·maven·axios·测试
小龙报1 小时前
《算法通关指南---C++编程篇(2)》
c语言·开发语言·数据结构·c++·程序人生·算法·学习方法
古一|1 小时前
Vue3中ref与reactive实战指南:使用场景与代码示例
开发语言·javascript·ecmascript
豆沙沙包?2 小时前
2025年--Lc201- 378. 有序矩阵中第 K 小的元素(排序)--Java版
java·线性代数·矩阵
华仔啊2 小时前
3 分钟让你彻底搞懂 Spring 观察者和发布者模式的本质区别
java·后端