Java内存模型详解

news2024/12/23 5:48:27

Java内存模型

Java内存模型(Java Memory Model)是Java虚拟机规范定义的,用于屏蔽因不同程序/硬件/操作系统上内存访问的差异,确保程序运行与设计一致,Java内存模型定义了Java虚拟机在计算机内存中的工作方式,确定了在共享内存系统中,多线程程序读写操作行为的规范,其是JVM中的一部分。

在Java内存模型中,规定所有变量都存储在主内存中,每条线程都有自己的本地内存(也叫做工作内存,是独属于单个线程的内存空间),线程在运行过程中在本地内存中完成变量的操作,并不是每次都和主存交互,如下图所示:

1.3.2.1

在上图中,当线程2对共享变量2进行修改时,共享变量2的内容如果还未同步到主存或者线程1获取共享变量2时,线程2修改操作未执行,都有可能导致线程1拿到的共享变量2的值与预期不同,进而导致程序异常。那么如何保证共享变量2的在线程1和线程2中的一致性呢?依赖于Java内存模型。

对于共享变量而言,Java内存模型中提出了三点特性:

  • 原子性:针对一个或多个操作,要么全部执行,要么全部不执行。执行过程中不会被打断;
  • 可见性:当有多个线程访问共享变量时,一个线程对数据的修改可以立即被其他线程感知并获取到新值;
  • 有序性:程序的执行顺序和开发者预设的代码顺序一致;

依赖这三种特性,进而保证并发场景下,程序运行的正确性,如下图所示:

1.3.2.2

那么Java内存模型中又是如何实现这三种特性的呢?主要依赖于限制处理器优化内存屏障两种方式,涉及到的概念主要包含重排序顺序一致性happens-beforeas-if-serial

重排序

在程序执行时,为了提高性能,处理器,编译器都会对程序指令进行重排序操作,在Java源代码转化成最终实际执行的指令序列中,会经历三种重排序:

  1. 编译器优化重排序:编译器在不改变单线程予以的前提下,可以重新安排语句的执行顺序
  2. 指令级重排序(处理器):现代处理器采用了指令级并行技术,来将多条指令重叠执行,如果不存在数据以来,助力器可以改变语句对应机器指令的执行顺序
  3. 内存系统重排序:由于处理器使用缓存,是的加载和存储操作看上去可能是乱序执行的

对于JMM而言,其禁止处理器重排序时通过在生成指令序列的适当位置插入内存屏障指令来实现的。

执行重排序具有以下条件:

  • 单线程环境下不能改变程序运行结果
  • 存在数据依赖关系的不能进行重排序

顺序一致性

顺序一致性是多线程环境下的理论参考模型,为程序提供可见性保证,顺序一致性具有以下特性:

  • 一个线程中的所有操作必须按照程序指定顺序执行
  • 所有线程都只能看到单一操作执行顺序,不论是否同步
  • 每个操作都必须原子执行且立刻对所有线程可见

happen-before

在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作必须存在happen-before关系,理论上讲,如果一个操作和另一个操作存在happen-before关系,那么这个操作的执行结果对后者可见且必然在后者前执行,两个操作存在happen-before关系并不代表这两个操作不可重排序,重排序后结果不变即可

as-if-serial

不管怎么重排序,程序的执行结果不能被改变,编译器,运行时和处理器都必须遵循该规则。

Java内存模型实现

前面了解了内存模型是什么以及需要解决的问题是什么?那么在Java中,并发环境下如何保证共享变量的三种特性呢?

使用Java中提供的并发处理关键字即可,各关键字及其对应的特性如下表:

特性关键字备注
原子性synchronized,原子变量等/
可见性volatile,synchronized,final等/
有序性Lock,RetreenLock,CountDownLatch等/

常用CPU概念

术语英文描述
内存屏障Memory Barriers一组处理器指令,用于实现对内存操作的顺序限制
缓冲行Cache Line缓存中可分配的最小单位,处理器填充缓存行时会加载整行,需要多个内存读取周期
原子操作Atomic Operations不可中断的一个或一系列操作
缓存命中Cache Hit访问地址在高速缓存行读取,则称为缓存命中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/449680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过SSH实现Linux与Windows之间的文件互传

目录 一 序言 二 准备工作 三 Windows端操作命令,实现文件互传 四 Linux端操作命令,实现文件互传 五 总结 一 序言 Linux和Linux以及Windows和Windows之间的文件共享互传,大家应该接触的都比较多,无非就是两种方式&#xff…

【C++类和对象】类和对象(上) {初识面向对象,类的引入,类的定义,类的访问限定符,封装,类的作用域,类的实例化,类对象模型,this指针}

一、面向过程和面向对象初步认识 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。…

1.2和1.3、GCC

1.2和1.3、GCC 1.2和1.3、GCC1.2.1、什么是GCC1.2.2、编程语言的发展1.2.3、GCC工作流程1.2.4、gcc和g的区别1.2.5、GCC常用参数选项实际操作①接下来进行预处理操作(test.c为需要预处理的源代码,test.i为要生成的目标代码)②汇编操作&#x…

iOS--SDWebImage源码

文章目录 前言它提供了UIImageView的一个分类,支持从网路上下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件。 SDWebImage简介官方图解主序列图(Main Sequence Disagram)顶层API图(Top Level API D…

XLA IR:HLO、LHLO、MHLO和LMHLO

XLA IR:HLO、LHLO、MHLO和LMHLO HLOLHLOMHLOLMHLOXLA IR 总结HLO->LMHLO xla基本编译流程如下: HLO Optimization: 硬件无关优化和硬件相关优化LHLO Codegen: 算子向量化和llvmir的生成HLO&LHLO是XLA-HLO;MHLO&LMHLO是MLIR-HLO&…

队列的基本操作(C语言链表实现)初始化,入队,出队,销毁,读取数据

文章目录 前言一、队列基本变量的了解二、队列的基本操作2.1队列的初始化(QueueInit)2.2入队(QueuePush)2.3判断是否为空队(QueueEmpty)2.4出队(QueuePop)2.5队列的队头数据&#xf…

分享BigDecimal金额计算的4种方式

基本介绍 金额计算这块通常都是基于2位小数的四舍五入,如果是自己的系统内部功能金额位数一般都是固定的,在正常的加减乘除运算逻辑都是保留同样位数的,但是乘法和除法相对比较特殊,在计算小数的部分可能会计算出更多位数的小数点…

【微服务】搭建Consul集群服务和Consul配置中心

文章目录 一、传统配置文件的弊端二、微服务配置中心三、主流的配置中心四、Consul 配置操作1.添加配置信息2.获取配置信息 五、单点服务器Consul集群 一、传统配置文件的弊端 静态化配置,例如env文件配置文件无法区分环境配置文件过于分散历史版本无法查看 配置中…

5.5、线程池同步机制类封装及线程池实现

代码地址 5.5、线程池同步机制类封装及线程池实现 1.线程池2.代码实现①锁Ⅰ、locker.hⅡ、locker.cpp ②条件变量Ⅰ、cond.hⅡ、cond.cpp ③信号量Ⅰ、sem.hⅡ、sem.cpp ④线程池Ⅰ、threadpool.hⅡ、threadpool.cpp 1.线程池 线程池是由服务器预先创建的一组子线程&#xf…

行为识别预警系统 opencv

行为识别预警系统通过pythonopencv网络模型技术,行为识别预警系统对现场画面中人的行为进行智能分析,发现违规行为自动抓拍告警,同步回传后台存档提醒值班人员及时处理。OpenCV的全称是Open Source Computer Vision Library,是一个…

CVE漏洞复现-CVE-2019-5736 Docker逃逸

CVE-2019-5736 Docker逃逸 Docker是什么? Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有…

JAVA实现AES加密、解密附代码

大家好,今天我们一起来学习 Java中的加密解密技术, java是一门面向对象的语言,使用它的开发人员都是非常聪明的人,他们对数据的安全性要求很高。在实际的应用中,我们都需要对数据进行加密、解密处理,这在 j…

【数据结构】第十三站:排序(上)

本文目录 一、排序概念二、插入排序1.插入排序的基本思想2.算法实现3.时间复杂度分析 三、希尔排序1. 希尔排序的思想2.希尔排序的代码实现3.希尔排序和插入排序的性能测试比较4.希尔排序的时间复杂度 四、直接选择排序1.基本思想2.直接选择排序的步骤3.直接选择排序的代码实现…

接口自动化测试用例如何设计?

说到自动化测试,或者说接口自动化测试,多数人的第一反应是该用什么工具,比如:Python Requests、Java HttpClient、Apifox、MeterSphere、自研的自动化平台等。大家似乎更关注的是哪个工具更优秀,甚至出现“ 做平台的 &…

音视频开发开发核心知识+小白入门必看基础知识

音视频开发是一个广泛的领域,它涉及到多个技术领域,包括音频编解码、视频编解码、媒体容器格式、流媒体传输、音视频处理等。以下是音视频开发的一些基础知识: 音频编解码器:音频编解码器是将数字音频信号编码成一种压缩格式&…

什么原因会导致香港轻量云服务器运行缓慢?

对于外贸企业主来说,想要为自己的网站选择一个可靠的主机供应商,并考虑使用香港轻量云服务器,则本文是必读的。本文将探讨租用香港轻量云服务器后遇到的运行缓慢的问题。下文这些因素被视为其中的主要因素。仔细分析它们中的每一个将帮助您确…

华为OD机试真题(Java),5键键盘的输出(100%通过+复盘思路)

一、题目描述 有一个特殊的5键键盘,上面有a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键。 a键在屏幕上输出一个字母a;ctrl-c将当前选择的字母复制到剪贴板;ctrl-x将当前选择的字母复制到剪贴板&#…

python 打包新方案

首先是打包一个最简单的python 代码使用 pyinstaller import os #直接读取文件获得python.exe 路径 # 待执行python路径 with open("path_run.txt","r",encoding"utf-8") as f:python_exe,pyf.readlines() os.system("{} {}".format(p…

关于Acunetix(AWVS)激活时候失败可能的方法

关于Acunetix(AWVS)激活的时候失败,可能的解决方法 如果自己的激活包大概率没有问题,但是自己却激活不了 可以在服务中关闭所有的进程,再进行文件替换 方法如下: 1.先卸载文件,卸载的干干净净 2.正常安装 3.安装完毕…

cuDNN 的初始设计

cuDNN V1.0在2014年的发布,并集成到 Caffe、Paddle 等深度学习框架中。论文 cuDNN: Efficient Primitives for Deep Learning 介绍了 NVIDIA 对于该库的设计和实现。近十年间,NVIDIA 迭代推出了8代架构,cuDNN 也更新到 8.9。硬件上引入了 Tensor Core&am…