Java内存模型相关面试题

article/2025/10/5 16:48:05

一、谈谈你对Java内存模型的理解可以吗?

对于Java内存模型大家千万不能和JVM内存模型弄混了,不一样的;
JVM内存模型是指JVM的内存分区,就是JVM分了几个区域;而Java内存模型是一种虚拟机规范。

首先来看下面一段代码,它的结果可能为1,也可能为2,咱们就借用这个代码来讲解一下Java内存模型;

public class WaitTest {static int data = 0;public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {data++;}}).start();new Thread(new Runnable() {@Overridepublic void run() {data++;}}).start();}}

根据下面这个流程图咱们讲解一下Java内存模型:

  1. Java的每个变量都是放在主内存中,每个线程呢又有自己独立的工作内存,这个工作内存只有当前线程能访问;
  2. 线程1首先会从主内存中读取data的值,以便后续load使用;
  3. 将data装入到工作线程的变量副本中;
  4. 进行data++操作;
  5. 将data++后的值赋值到工作线程的变量副本中;
  6. 将data保存到主内存中,以便后续write使用;
  7. 将data写入到主内存中;

线程2是同样的操作,其实Java内存模型主要的操作就是下图中的6个流程,还有另外两个是lock和unlock;

  • lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态;
  • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
  • read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用;
  • load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中;
  • use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作;
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作;
  • store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作;
  • write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中;
    在这里插入图片描述

二、你知道Java内存模型中的原子性、有序性、可见性是什么吗?

沿用上面的例子咱们来讲讲这几个特性

  • 可见性
    如果线程1对data进行++后线程2立马就能够读取到最新的值,那么就可以说data是具有可见性的,反之则没有;
  • 原子性
    线程1在进行data++操作时,线程2不能够对data进行操作,那么这个操作就具有原子性,也就是加锁,当下只有一个线程能够执行该操作;
  • 有序性
    指data++操作的代码顺序是有序的,因为CPU在执行代码时会进行指令重排,增加代码执行效率,什么情况下会重排,咱们接下来会讲到;

三、能从Java底层角度聊聊volatile关键字的原理吗?

volatile解决了多个线程之间的可见性,那volatile是如何做到的呢,咱们继续使用下面这个流程图来讲解,假设线程2比线程1慢执行,当线程1已经进行完data++并写入到主内存时,会将其他有使用到data的线程内保存的变量副本设置成失效状态,此时如果线程2正要去use data变量,发现data变量此时为失效状态,那么就会重新去主内存中读取data,这就做到了data的可见性。
在这里插入图片描述

四、你知道指令重排以及happens-before原则是什么吗?

CPU和编译器为了提升程序的执行效率,会对写好的代码进行执行顺序的调换,即写在后面的代码可能会先于前面的代码执行,这就是指令重排,但是并非所有的程序都会进行指令重排,因为一旦程序执行顺序改变可能会造成逻辑错误,所以只有不满足happens-before原则的程序才可能会被指令重排;

happens-before原则一共有8个:

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
  • 锁定规则:一个unLock操作先行发生于面对同一个锁的lock操作;
  • volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个volatile变量的读操作,volatile变量写,再是读,必须保证是先写,再度;
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作;
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发送;
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;

以上这些规则有些拗口,大家没有必要去背他,只需要知道什么是指令重排,happens-before原则是啥,大概举例几点,还有一个就是volatile可以保证程序的有序性就可以了;

五、volatile底层是如何基于内存屏障保证可见性和有序性的?

这一块是比较复杂的,所以咱们只要记住两点:

  • lock指令:volatile保证可见性
    对volatile修饰的变量,执行写操作的话,JVM会发送一条lock前缀指令给CPU,CPU在计算完之后会立即将这个值写回主内存,同时因为有MESI缓存一致性协议,所以各个CPU都会对总线进行嗅探,自己本地缓存中的数据是否被别人修改;
    如果发现别人修改了某个缓存的数据,那么CPU就会将自己本地缓存的数据过期掉,然后这个CPU上执行的线程在读取那个变量的时候,就会从主内存重新加载最新的数据了;
    所以主要是lock前缀指令+MESI缓存一致性协议。

  • 内存屏障:volatile禁止指令重排序
    加入了屏障之后,就能够禁止volatile和前后的代码进行指令重排。


http://chatgpt.dhexx.cn/article/n9PRYdxI.shtml

相关文章

什么是Java内存模型?

点击上方“程序员小灰”,选择“置顶公众号” 有趣有内涵的文章第一时间送达! 本文转载自公众号 占小狼的博客 说”JVM内存模型“,有人会说是关于JVM内存分布(堆栈,方法区等)这些介绍,也有地方说…

Java面试--Java内存模型

面试题:你了解Java内存模型吗?(顺丰面试题) 面试题:程序内存的分布,五个部分(360面试题) 一、Java程序的执行过程: Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中…

JAVA内存模型与JVM内存模型

JAVA内存模型(JMM)与JVM内存模型 1、JAVA内存模型保证了在多线程环境下,对共享变量读写的原子性、可见性和有序性的一系列规范。 2、JVM内存模型规定了JAVA虚拟机在运行时使用的内存的各个分区及其作用。JAVA内存模型 原子性: 通过 synchronized、lock实现&#x…

Java内存模型(JMM)详解

目录 一、为什么要有内存模型二、CPU和缓存一致性2.1 为什么需要CPU cache2.2 三级缓存(L1、L2、L3)2.3 乱序执行优化 三、java内存模型3.1 JVM对Java内存模型的实现3.2 Java内存模型和硬件架构之间的桥接3.3 Java内存模型 - 同步八种操作3.4 Java内存模…

jvm内存模型和java内存模型

初识java虚拟机,就碰到一系列不懂的问题。我们以前常说java把局部变量放在栈里,new出来的变量放在堆里,然后堆里的数据不定时就给回收了。然后,如果是多线程的话,每个线程自己都有会一个私有的虚拟机栈,运行…

JAVA内存模型与JVM内存模型的区别

** JAVA内存模型与JVM内存模型的区别 ** 直接进入正题 **JAVA内存模型: Java内存模型规定所有的变量都是存在主存中,每个线程都有自己的工作内存。线程堆变量的操作都必须在工作内存进行,不能直接堆主存进行操作,并且每个线程…

【3】Java内存模型

目录 知识点1:Java内存模型 知识点2:Volatile 1、什么是Volatile 2、Volatile特性 3、Volatile与Synchronized区别 知识点3:重排序 1、数据依赖性 2、as-if-serial语义 3、程序顺序规则 4、重排序对多线程的影响 知识点1&#xff1a…

Java内存模型详解

文章目录 一、什么是JMM?为什么需要JMM?二、JMM 如何抽象线程和主内存之间的关系?三、Java 内存区域和 JMM 有何区别?四、happens-before原则五、总结 一、什么是JMM?为什么需要JMM? Java 是最早尝试提供内…

java内存模型概述

java内存模型 为了控制线程之间的通信,(完成底层封装) 用来屏蔽掉各种硬件和操作系统之间的内存访问差异,以实现让Java程序在各平台下都能达到一致的内存访问效果。 JMM目标:定义程序中各个变量的访问规则&#xff0c…

理解Java内存模型(JMM)

本篇的写作思路是先阐明Java内存区域划分、硬件内存架构、Java多线程的实现原理与Java内存模型的具体关系,在弄明白它们间的关系后,进一步分析Java内存模型作用以及一些实现手段 理解Java内存区域与Java内存模型 Java内存区域 Java虚拟机在运行程序时会…

Java 内存模型

Java 内存模型(Java Memory Model),简称 JMM。 JVM 中试图定义一种 JMM 来屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。 一、物理内存模型 物理机遇到的并发问题与虚拟机中…

Java内存模型

Java内存模型 1.内存模型概念图2.线程共享区方法区常量池运行时常量池全局字符串池class文件常量池 堆空间3.线程独占区虚拟机栈本地方法栈程序计数器 4.对象的创建 1.内存模型概念图 2.线程共享区 方法区 方法区也是线程共享区用于储存虚拟机加载的类信息(类的版…

一文看懂Java内存模型(JMM)

文章目录 Java内存模型介绍总览图Java内存模型图线程、主内存、工作内存关系图CPU缓存架构图Java内存模型与硬件内存架构的关系 什么是Java内存模型Java内存模型的意义Java内存模型规范 Java内存模型的主要结构1、程序计数器(Program Counter Register)2…

SPSS建立时间序列模型

原始数据可能并不是时间序列,因此,对这样的数据建立时间序列模型,分为以下几步: 1 生成时间序列:定义新的时间变量,并对原始数据进行平稳处理 a)定义时间变量: 选择按什么时间序列进行定义&am…

时间序列模型(ARIMA和ARMA)完整步骤详述

我于2019年发布此篇文章至今收获了许多人的指点,当时的代码的确晦涩难懂,近期有空,将代码重新整理了一遍,重新发送至此。希望能够帮助大家更好地理解。 建模步骤: 目录 数据包和版本申明 步骤一:数据准备…

机器学习之时间序列模型

一、时间序列概念 在生产和科学研究中,对某一个或一组变量x(t)进行观察测量,将在一系列时刻t1, t2, …, tn (t为自变量)按照时间次序排列,并用于解释变量和相互关系的数学表达式。在相等的时间间隔内收集到的不同时间点的数据集合我们称之为时…

数学建模学习笔记(十)——时间序列模型

文章目录 一、时间序列综述二、时间序列数据以及基本概念三、时间序列分解四、指数平滑模型五、一元时间序列分析的模型六、AR(p)模型七、MA(q)模型八、ARMA(p, q)模型九、模型选择:AIC 和 BIC …

时间序列模型步骤教程(ARIMA)

目录 0、前言一、数据准备&探索1、平稳性1.1 平稳性检验1.2 数据处理(平滑、变换、差分、分解)1.2.1 对数变换1.2.2 平滑法(移动平均&指数平均)1.2.3 差分法1.2.4 分解 2、非白噪声检验 二、模型(ARIMA&#x…

时间序列模型分析

目录 一个引言 定义 确定性时间序列分析方法概述 确定性时间序列模型类型 移动平均法 简单移动平均法 加权移动平均法 趋势移动平均法 指数平滑法 一次指数平滑法 1.预测模型​编辑 2.加权系数的选择​编辑 3.初始值的确定​编…

时间序列模型相关说明和模型介绍

一、什么是时间序列? 时间序列是在规律性时间间隔记录的观测值序列。依赖于观测值的频率,典型的时间序列可分为每小时、每天、每周、每月、每季度和每年为单位记录。 import pandas as pd df pd.read_csv(https://raw.githubusercontent.com/selva86/datasets/d…