当前位置: 首页 > news >正文

java八股文面试[多线程]——主内存和工作内存的关系

JAVA内存模型(JMM)
共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。
上面的工作内存其实是java内存模型抽象出来的概念,下面简要介绍一下java内存模型(JMM)。
java内存模型(java memory model): 描述了java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。

不同的平台,内存模型是不一样的,我们可以把内存模型理解为在特定操作协议下,对特定的内存高速缓存进行读写访问的过程抽象。Java 虚拟机规范中试图定义一种 Java 内存模型(Java Memory Model,简称 JMM)屏蔽掉各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果,不必因为不同平台上的物理机的内存模型的差异,对各平台定制化开发程序。
更具体一点说,Java 内存模型提出目标在于,定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。

在这里插入图片描述

 

从上图可以得出结论:

  • 所有的变量都存储在主内存
  • 每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存该变量的一份拷贝)。

JMM关于synchronized的两条规定:

  1. 线程解锁前,必须把共享变量的最新值刷新到主内存中
  2. 线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值。(加锁和解锁需要是同一把锁)

线程解锁前对共享变量的修改在下次加锁前对其他线程可见。

JVM主内存与工作内存描述

JVM将内存为主内存工作内存两个部分。

主内存: 主要包括本地方法区和 

  • Java 内存模型规定了所有变量都存储在主内存(Main Memory)中(此处的主内存与介绍物理硬件的主内存名字一样,两者可以互相类比,但此处仅是虚拟机内存的一部分)。

工作内存: 每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的和 对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。

  • 每个线程都有自己的工作内存(Working Memory,又称本地内存.),线程的工作内存中保存了该线程使用到的变量,该变量是主内存中的共享变量的副本拷贝
  • (工作内存是 JMM 的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。)

在这里插入图片描述

 线程执行的时候,将首先从主内存读值,再load到工作内存中的副本中,然后传给处理器执行,执行完毕后再给工作内存中的副本赋值,随后工作内存再把值传回给主存,主存中的值才更新。
在这个过程中如果出现多个线程同时在处理这些值,岂不是会出现并发问题

在这里插入图片描述

1、所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共享的
2、每个线程都有自己的工作内存,工作内存中保存的是主存中某些变量的值的副本拷贝,线程对变量的所有操作都必须在工作内存中进行,不能直接读写主内存中的变量。
3、线程之间无法直接访问对方的工作内存中的变量值的,线程间变量的传递均需要通过主内存来完成。
这种划分与Java运行时内存区域中堆、栈、元空间等的划分是不同层次的划分,两者基本没有关系。硬要联系的话,大致上主内存对应Java堆中对象的实例数据部分、工作内存对应栈的部分区域;从更低层次上说,主内存对应物理硬件内存、工作内存对应寄存器和高速缓存

JVM内存间交互规则

关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存之类的实现细节,Java 内存模型中定义了下面 8 种操作来完成。
在这里插入图片描述

  1. Lock(锁定):作用于主内存中的变量,把一个变量标识为被一个线程独占的状态。
  2. Unlock(解锁):作用于主内存中的变量, 将一个变量从锁定状态(Lock)释放出来,释放后的变量才可以被其他线程锁定(Lock)
  3. Read(读取):作用于主内存中的变量,将一个变量的值从主内存传输到工作内存中,以便随后的load操作使用
  4. Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。
  5. Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。(每当虚拟机遇到一个需要使用到变量的值的字节码指令时就会执行这个操作。)
  6. Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。(每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。)
  7. Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中,以便随后 write 操作使用。
  8. Write(写入):作用于主内存中的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中。

需知:

  • 在将变量从主内存读取到工作内存中,必须顺序执行read(读取)、load(加载)
  • 要将变量从工作内存同步回主内存中,必须顺序执行store(存储)、write(写入)

这8种操作必须遵循以下规则:

  1. 不允许read(读取)和load(加载)、store(存储)和write(写入)操作之一单独出现。即不允许一个变量从主内存被读取了,但是工作内存不接受,或者从工作内存回写了但是主内存不接受。

    不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步会主内存中

  2. 不允许一个线程丢弃它最近的一个assign(赋值)操作,即变量在工作内存被更改后必须同步改更改回主内存。即:执行store(存储),write(写入)操作

  3. 工作内存中的变量在没有执行过assign(赋值)操作时,不允许无意义的同步回主内存。 即:执行store(存储),write(写入)操作

  4. 在执行use(使用)前必须已执行load(加载),在执行store(存储)前必须已执行assign(赋值)

  5. 一个变量在同一时刻只允许一个线程对其执行lock操作,一个线程可以对同一个变量重复执行多次lock,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。lock和unlock必须成对出现。

  6. 一个线程在lock一个变量的时候,将会清空工作内存中的此变量的值,执行引擎在use(使用)前必须重新read(读取)和load(加载)初始化变量的值。

  7. 在执行unlock之前,必须首先执行了store(存储)和write(写入)操作

    对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)

  8. 线程不允许unlock其他线程lock操作。并且unlock操作必须是在本线程的lock操作之后。

    如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。

从上面可以看出,把变量从主内存复制到工作内存需要顺序执行read、load,从工作内存同步回主内存则需要顺序执行store、write。总结:

  • read、load、use必须成对顺序出现,但不要求连续出现。assign、store、write同之;
  • 变量诞生和初始化:变量只能从主内存“诞生”,且须先初始化后才能使用,即在use/store前须先load/assign;
  • lock一个变量后会清空工作内存中该变量的值,使用前须先初始化;unlock前须将变量同步回主内存;
  • 一个变量同一时刻只能被一线程lock,lock几次就须unlock几次;未被lock的变量不允许被执行unlock,一个线程不能去unlock其他线程lock的变量。

JVM先行发生原则

Java内存模型具备一些先天的“有序性”,即不需要通过任何同步手段(volatile、synchronized等)就能够得到保证的有序性,这个通常也称为happens-before原则

 

知识来源:

【23版面试突击】你知道主内存和工作内存的关系?_哔哩哔哩_bilibili

【Java多线程】内存模型JMM—主内存与工作内存分析_主内存和工作内存_Archie_java的博客-CSDN博客

相关文章:

java八股文面试[多线程]——主内存和工作内存的关系

JAVA内存模型(JMM)共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。 上面的工作内存其实是java内存模型抽象出来的概念,下面简要介绍一下java内存模型(JMM&…...

技术分享 | LSM,Linux 内核的安全防护盾

计算机安全是一个非常重要的概念和主题,它不仅仅可以保护用户个人信息和资产的安全,还可以影响到用户在使用过程中的体验;但同时,它也是一个很抽象的概念,关于其相关文献和资料不计其数,但它究竟是什么、包…...

http服务(Apache 2.4.57)源码编译及使用

这里安装的是Apache 2.4.57版本 1.下载源码包及编译安装 下载地址 # 下载 wget https://archive.apache.org/dist/httpd/httpd-2.4.57.tar.gz # 如果系统自带httpd这个软件要删除掉,两个软件不能同时运行 rpm -e httpd --nodeps # 安装依赖环境 yum -y install apr apr-dev…...

【1day】H5S视频平台未授权漏洞学习

目录 一、漏洞描述 二、资产测绘 三、漏洞复现 四、漏洞修复 一、漏洞描述 H5S视频平台是一个基于Web技术的视频播放和流媒体管理平台。它提供了一套完整的解决方案,用于在网页上播放和管理视频内容。H5S视频平台存在未授权漏洞,泄露内网rtsp服务集群的服务集群的和H5_…...

企业架构LNMP学习笔记3

服务器基本环境配置: 1、安装虚拟机,centos7.9 操作系统; 2、网络配置; 3、机器名FQDN设置; 4、DNS解析设置,本地hosts设置; 5、配置yum源环境; 6、vim安装配置; …...

使用Spring Boot和Kafka实现消息发送和订阅

文章目录 一,新建Spring Boot1,Maven配置2,无法识别为SpringBoot项目3,无效的源发行版4,无法访问SpringApplication5,运行直接Finish6,服务运行成功 二,安装启动Kafka1,下…...

探讨uniapp的组件使用的问题

1 视图容器 1.1 view Flex是Flexible Box的缩写,意为“弹性布局”,用来为盒状模型提供最大的灵活性。 当设置display: flex后,继续给view等容器组件设置flex-direction:row或column,就可以在该容器内按行或列排布子组件。uni-ap…...

【跟小嘉学 Rust 编程】十七、面向对象语言特性

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学…...

mall :rabbit项目源码解析

文章目录 一、mall开源项目1.1 来源1.2 项目转移1.3 项目克隆 二、RabbitMQ 消息中间件2.1 rabbit简介2.2 分布式后端项目的使用流程2.3 分布式后端项目的使用场景 三、安装RabbitMQ(Win10)3.1安装erLang语言,配置环境变量3.2 安装RabbitMQ服务端3.3 测试安装效果 四…...

JDBC连接数据库

目录 一.什么是JDBC 二.JDBC的实现步骤 三.简单使用JDBC 一.什么是JDBC JDBC是Java数据库连接,是java中提供数据库访问的Java API,它为关系型数据库的提供了统一访问规范。 二.JDBC的实现步骤 1.创建数据库连接 这里有两种方式: DataSource创建,提…...

Linux学习之Ubuntu 20中OpenResty的nginx目录里内容和配置文件

参考的文章是《nginx配置详解》 可以参考我以前的文章安装OpenResty。 cd /usr/local/openresty切换目录,ls -l查看目录里边的内容。 我的系统中,nginx目录是/usr/local/openresty/nginx,在这个目录里边有一些目录,如下&#xff…...

使用axi_quad_spi操作spi_flash

文章目录 基本测试情况IP支持的命令 基本测试情况 有spi_flash需要访问,为简单计,选择使用axi_quad_spi进行操作。开始时,将IP配置成如下参数, 这样配置,是想着能够适应各家的FLASH(实际使用的则是micron…...

Linux:tomcat (源码包安装)(官网下载-安装-启动-配置-等等等-----从入门到入土)

介绍 Apache Tomcat软件是一个开源实现 Jakarta Servlet、Jakarta Server Pages、Jakarta Expression Language、Jakarta WebSocket、Jakarta Annotations 和 Jakarta Authentication 规范。 这些规范是Jakarta EE平台的一部分。 Apache Tomcat软件是在开放和参与式中开发的。 …...

中科驭数以DPU先进计算技术,夯实下一代金融IT基础设施底座

由中国计算机学会主办的第19届CCF全国高性能计算学术年会(CCF HPC China 2023)于8月23日至26日在青岛成功召开。在“高性能金融计算”主题论坛上,中科驭数高级副总裁、CTO卢文岩应邀发表了题为《DPU先进计算技术助力下一代交易底座》的演讲&a…...

Android 手游聚合SDK小知识(二) 聚合分包

更新: 在上一篇文章中,我们介绍了如何聚合SDK的基本原理,介绍了聚合SDK的接口设计,那么当CP接入了我们的聚合SDK,给了我们游戏apk包时,这时我们又当如何分发渠道包呢? 分发渠道包:…...

【RISC-V】RISC-V寄存器

一、通用寄存器 32位RISC-V体系结构提供32个32位的整型通用寄存器寄存器别名全称说明X0zero零寄存器可做源寄存器(rs)或目标寄存器(rd)X1ra链接寄存器保存函数返回地址X2sp栈指针寄存器指向栈的地址X3gp全局寄存器用于链接器松弛优化X4tp线程寄存器常用于在OS中保存指向进程控…...

Python爬虫异常处理实践:处理被封禁和网站升级问题

在这篇文章中,我们将一起探讨Python爬虫异常处理实践,特别关注处理被封禁和网站升级问题。让我们一起来看看如何解决这些问题,提高我们爬虫程序的稳定性和可靠性。   首先,我们要了解为什么会遇到这些问题。网站封禁爬虫的原因主…...

重大工程建造云服务平台源码 SpringCloud+Vue

技术架构: 微服务JavaSpring Cloud VueUniApp MySql 开发语言:Java 开发工具:Idea 前端框架:Vue 后端框架:Spring Cloud 数 据 库:MySql 移 动 端:UniApp 系统端口:PC端&…...

MyBatisPlus简单入门

1、简单介绍MyBatisPlus MyBatisPlus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,完全去SQL化,封装好了大量的CRUD操作。甚至吧CRUD操作封装到了Service层,可以直接在Controller调用现成的CRUD服务层&#xff0c…...

神经网络入门

神经网络的基本骨架 1. nn.Module的使用 所有的模型都要继承 Module 类需要重写初始化函数和运算步骤函数 eg: import torch.nn as nn import torch.nn.functional as Fclass Model(nn.Module): # 继承父类Module def __init__(self): # 重写初始化函数super()…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

蓝桥杯 冶炼金属

原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...