JMM内存模型详解

news2024/12/23 13:51:44

1、概要

JMM全称叫Java Memory Model(Java内存模型),什么是JMM,为什么要设置JMM,要弄清楚这个,咱们要先从计算机硬件存储体系说起。

2、计算机硬件存储体系

Window任务管理器
Mac资源管理器

 

window和mac是两种不同的操作系统,但是从上图可以看出都有内存、缓存。咱们都知道CPU的运算速度是最快了,为了解决CPU和内存之间的运算速度不对等问题,在CPU和内存之间增加了一层缓存。再比如现实开发的需求,商品秒杀,库存是存储在DB中的,每次从DB中拿取库存并修改是非常耗时的,为了解决此问题我们需要在DB和用户之间增加一层或者多级缓存。这就是操作系统的内存模型。

3、JMM

Java应用程序需要跑在不同的操作系统上,那就要准守操作系统的内存模型规则。虽然Java是可以直接复用操作系统层面内存模型的,但是不同的操作系统内存模型不同。如果直接复用操作系统层面的内存模型,就可能会导致同样一套代码换了一个操作系统就无法执行了。因为Java 语言是跨平台的,所以JVM规范试图定义一种Java内存模型(JMM)来屏蔽各种硬件和操作系统的内存访问模型,这就是JMM设计的初衷。

JMM本身是一种抽象的概念并不真实存在,它仅仅描述的是一组约定或者规范,通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式,并决定一个线程对共享变量的写入以及如何变成对另一个线程可见,关键技术点都是围绕多线程的原子性、可见性和有序性这三大特性展开的。

那JMM到底能干嘛呢?

①、通过JMM来实现线程和主内存之间的抽象概念

②、屏蔽各个硬件平台和操作系统的内存访问差异以实现让Java程序在各种平台下都能达到一致的内存访问效果

4、JMM三大特性

4.1、可见性

是指当一个线程修改了某一个共享变量,其他线程是否能够立即知道该变更,JMM规定了所有的变量都存储在主内存中。每个线程都有一个本地内存(共享变量副本)。线程获取共享变量的顺序:先是从判断本地内存获取,如果没有则取主内存获取并存储在本地内存中。线程修改共享变量顺序:先是修改本地内存,然后将本地内存同步到主内存(时间未知)

由于系统主内存共享变量修改被写入的时机是不确定的,多线程并发下很可能出现”脏读“(读取的数据不是最新的),所以每个线程都有自己的本地内存,线程自己的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在自己的本地内存中进行,而不能直接读写主内存中的变量。不同线程之间也无法直接访问对方本地内存中的变量,线程间变量值的传递均需要通过主内存完成。

4.2、原子性

对于同一个操作中的多个执行,要么全部执行成功要么全部执行失败。

在 Java 中,可以借助synchronized 、各种 Lock 以及各种原子类实现原子性。

synchronized 和各种 Lock 可以保证任一时刻只有一个线程访问该代码块,因此可以保证原子性。各种原子类是利用 CAS (compare and swap) 操作(可能也会用到 volatile或者final关键字)来保证原子操作。

4.3、有序性

对于一个线程的执行代码而言,我们总是习惯性认为代码的执行总是从上到下,有序执行。但是为了提升性能,编译器和处理器通常会对指定序列进行重新排序。Java规范规定JVM线程内部维持顺序化语义,即只要程序最终结果与它顺序化执行的结果相等,那么指令的执行顺序可以域代码顺序不一致,此过程叫做指令重排序。

那指令重排序的优缺点是什么呢?

JVM能根据处理器特性适当的对机器指令进行重排序,使机器指令更符合CPU的执行特性,最大限度的发挥机器性能。

指令重排序可以保证串行(单线程)语义一致,但是没有义务保证多线程访问的语义也一致(即可能产生”脏读“),简单说,两行以上不相干的代码执行的时候有可能先执行的不是第一行,不见得是从上到下顺序执行,执行顺序会被优化。例如以下代码,因为两行代码没有相关性,执行的时候有可能执行第二行而不是第一行。


        //第一行
        int x = 0;
        //第二行
        int y = 1;
        //第三行
        int z = x + y;

多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。

package com.lc.test03;

/**
 * @author liuchao
 * @date 2023/4/10
 */
public class Test01 {

    int x = 0;
    int y = 0;

    public static void main(String[] args) {
        Test01 test01 = new Test01();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                test01.set();
                test01.call();
            }, String.format("t-%", i)).start();
        }
    }

    public void set() {
        x = 2;
        y = 3;
    }

    public void call() {
        if (y == 3) {
            System.out.println("----在多线程下由于重排序的存在,输出的X值可能为0:" + x);
        }
    }

}

5、JMM规范下的变量读取过程

①、定义所有的变量都存储在物理主内存中

②、每个线程都有自己独立的本地内存,里面保存该线程使用到的变量的副本(从主内存拷贝过来的)

③、线程对共享变量的所有操作都必须先在自己的本地内存中进行后再回写到主内存,不能直接操作主内存

④、不同线程之间的本地内存是隔离的,线程间的变量传递需要通过主内存来进行。

 

 

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

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

相关文章

Flink 优化 (二) --------- 状态及 Checkpoint 调优

目录一、RocksDB 大状态调优1. 开启 State 访问性能监控2. 开启增量检查点和本地恢复3. 调整预定义选项4. 增大 block 缓存5. 增大 write buffer 和 level 阈值大小6. 增大 write buffer 数量7. 增大后台线程数和 write buffer 合并数8. 开启分区索引功能9. 参数设定案例二、Ch…

拐点!智能座舱破局2023

“这是我们看到的整个座舱域控渗透率&#xff0c;2022年是8.28%&#xff0c;主力的搭载车型仍然是30-35万区间。”3月29日&#xff0c;2023年度&#xff08;第五届&#xff09;高工智能汽车市场峰会上&#xff0c;高工智能汽车研究院首发《2022-2025年中国智能汽车产业链市场数…

WRF中替换LAI数据

WRF中替换LAI数据 本次下载的LAI数据是GLASS中的AVHRR(1981-2018)(V50)&#xff0c;可以从这个这里获取数据GLASS_AVHRR_LAI数据集。由于我需要做一个时间序列的模拟&#xff0c;总共下载了从1990-2018年灌溉季3-9月份对应的天数为73&#xff0c;105&#xff0c;137&#xff0…

人工智能大时代——AIGC综述

生成式AI分类 模型按照输入输出的数据类型分类&#xff0c;目前主要包括9类。 有趣的是&#xff0c;在这些已发布大模型的背后&#xff0c;只有六个组织&#xff08;OpenAI, Google, DeepMind, Meta, runway, Nvidia&#xff09;参与部署了这些最先进的模型。 其主要原因是&am…

11.基于粒子群算法的含风光燃储微网优化调度(论文复现)

说明书 相关代码资源&#xff1a;基本算法智能微电网粒子群优化算法,微源&#xff1a;光伏、风机、发电机、储能等 基于多目标算法的冷热电联供型综合能源系统运行优化 基于多目标粒子群算法冷热电联供综合能源系统运行优化 MATLAB代码&#xff1a;基于粒子群算法的含风光燃…

0成本 使用home assistant远程开关机电脑

环境&#xff1a;dockerwin10HACS 问题&#xff1a;在外网手机上远程开关机家中电脑 解决办法&#xff1a;开机&#xff1a;WOL&#xff0c;关机ssh命令 背景&#xff1a;在部署HACS后&#xff0c;便想用HACS中的命令来开关机windows电脑&#xff0c;开机很简单&#xff0c;使用…

暴力破解之验证码识别

文章目录背景操作步骤1、安装python模块2、安装Captcha-killer模块3、尝试进行验证码识别背景 渗透测试过程中&#xff0c;现在验证码越来越多&#xff0c;这对测试的时候遇到的阻力不小&#xff0c;一位大佬给我安利了一个burp插件&#xff0c;Captcha-killer&#xff0c;可以…

ROS开发之如何使用ICM20948 IMU模块?

文章目录0.引言1.创建工作空间2.获取IMU功能包并编译3.检查IMU端口4.启动launch显示IMU测量结果0.引言 笔者研究课题涉及多传感器融合&#xff0c;除了前期对ROS工具的学习&#xff0c;还需要用IMU获取数据&#xff0c;对其他传感器的姿态纠正。本文使用IMU模块获取姿态数据。I…

华为乾坤王辉:新一代网络安全融合体系,筑牢企业数字化转型基石丨2023 INSEC WORLD

科技云报道原创。 随着数字化时代的到来&#xff0c;网络安全形势持续动荡。 围绕产业未来发展趋势、信息安全产业可持续发展、信息安全技术发展路径等话题&#xff0c;一场信息安全行业年度盛会——INSEC WORLD世界信息安全大会在西安盛大召开。 本届大会汇聚了近50位海内…

大数据技术(入门篇) --- 使用 Spring Boot 操作 CDH6.2.0 Hadoop

前言 本人是web后端研发&#xff0c;习惯使用spring boot 相关框架&#xff0c;因此技术选型直接使用的是spring boot&#xff0c;目前并未使用 spring-data-hadoop 依赖&#xff0c;因为这个依赖已经在 2019 年终止了&#xff0c;可以点击查看 &#xff0c;所以我这里使用的是…

防火墙的IPSECVPN点到点实验 dsvpn多层分支实验

目录 防火墙的IPSECVPN点到点实验 dsvpn多层分支实验 ​编辑 防火墙的IPSECVPN点到点实验 配置路由器接口IP 配置接口防火墙IP 写放通的策略 ping对端防火墙的接口看是否能ping通 ipsec进行配置 配置往返流量 dsvpn多层分支实验 先配置IP 2&#xff0c;配置静态IP 3&#xf…

拦截导弹 导弹防御系统

拦截导弹 & 导弹防御系统拦截导弹导弹防御系统拦截导弹 题目链接:acwing1010. 拦截导弹 题目描述&#xff1a; 输入输出: 分析&#xff1a; 第一个问题为输出最长递减子序列&#xff0c;由于导弹数在1000以内所以采用时间复杂度为O(n2)O(n^2)O(n2)或者O(nlogn)O(nlogn)O…

介绍一款idea神级插件【Bito-ChatGPT】

什么是Bito&#xff1f; Bito是一款在IntelliJ IDEA编辑器中的插件&#xff0c;Bito插件是由ChatGPT团队开发的&#xff0c;它是ChatGPT团队为了提高开发效率而开发的一款工具。ChatGPT团队是一支专注于自然语言处理技术的团队&#xff0c;他们开发了一款基于GPT的自然语言处理…

[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符

另类字符 回忆上次内容 上次再次输出了大红心♥ 找到了红心对应的编码黑红梅方都对应有编码 原来的编码叫做 ascii️ \u这种新的编码方式叫unicode包括了 中日韩字符集等 各书写系统的字符集 除了这些常规字符之外 还有什么好玩的东西呢&#xff1f; 颠倒字符 这个网站可以…

DQN基本概念和算法流程(附Pytorch代码)

❀DQN算法原理 DQN&#xff0c;Deep Q Network本质上还是Q learning算法&#xff0c;它的算法精髓还是让Q估计Q_{估计}Q估计​尽可能接近Q现实Q_{现实}Q现实​&#xff0c;或者说是让当前状态下预测的Q值跟基于过去经验的Q值尽可能接近。在后面的介绍中Q现实Q_{现实}Q现实​也…

提高工作效率必备,5款实用的Windows系统工具推荐

每次分享实用的软件,都会给人一种踏实和喜悦的感觉,这也是我热衷于搜集和推荐高效工具软件的原因。 音量控制——EarTrumpet EarTrumpet是一款音量控制工具&#xff0c;可以让你更方便地调节Windows系统中不同应用程序的音量。你可以使用EarTrumpet来替代系统自带的音量混合器…

表单设计器开源的定义和应用场景布局介绍

为了实现提质增效的办公自动化&#xff0c;表单设计器开源工具的应用变得广泛起来。在低代码开发市场昌盛发展的今天&#xff0c;不少企业期望通过快速、现成的快速配置表单工具实现高效率表单制作&#xff0c;那么&#xff0c;现在给大家介绍的这款开发易用性强、组件丰富、高…

设计模式 -- 门面模式

前言 月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂) 央是一片海洋,海乃百川,代表着一块海绵(吸纳万物) 泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出) 月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容 希望大家一起坚持这个过程,也同…

stable-diffusion真的好用吗?

hi&#xff0c;各位大佬&#xff0c;今天尝试下diffusion大模型&#xff0c;也是CV领域的GPT&#xff0c;但需要prompt&#xff0c;我给了prompt结果并不咋滴&#xff0c;如下示例&#xff0c;并附代码及参考link 1、img2img 代码实现&#xff1a; import torch from PIL im…

PageHelper的使用

这个分页插件是在Mybatis的环境中使用的&#xff0c;所以项目需要导入Mybatis依赖 更加详细的用法看官方文档&#xff1a;PageHelper官网 在Mybatis中使用 前提条件 引入依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pa…