JVM内存结构Java内存模型Java对象模型

news2024/9/20 6:33:06

导图:

        https://naotu.baidu.com/file/60a0bdcaca7c6b92fcc5f796fe6f6bc9

1.JVM内存结构&&Java内存模型&&Java对象模型

1.1.JVM内存结构

1.2.Java对象模型

Java对象模型表示的是这个对象本身的存储模型,JVM会给这个类创建一个instanceKlass保存在方法区,用来在JVM层表示该Java类,当在Java代码中使用new创建一个对象时JVM会创建一个instanceOopDesc对象,这个对象中包含了对象头以及实例数据;

1.3.Java内存模型(JMM)

1.3.1.为什么需要JMM?

        1.C语言不存在内存模型概念;

        2.Java程序依赖处理器,不同处理器结果不一样;

        3.无法保证并发安全;

1.3.2.什么是JMM?

        JMM是一组规范,需要各个JVM的实现来遵循JMM规范,以便开发者可以利用这些规范更方便的开发多线程程序;如果没有这样一个JMM内存模型来规范,那么很可能经过了不同JVM的不同规则的重排序后,导致不同虚拟机上运行的结果不一样;JMM不仅仅作为一组规范它同时还是“工具类”、“synchronized”、“Lock”等的原理;

1.3.3.JMM核心内容

        1.重排序

        2.可见性

        3.原子性

        并发编程线程安全问题的根源在于:重排序、可见性;

1.3.3.1.重排序
1.3.3.1.1.什么是重排序

        代码在JVM中的执行顺序和在Java代码中的顺序不一致;(代码指令执行顺序并不是严格按照语句顺序执行的,这就是重排序);

1.3.3.1.2.重排序代码案例
import java.util.concurrent.CountDownLatch;
/**
 * 演示代码执行时被JVM重排序
 */
public class OutOfOrderExecution{
    private static int x = 0,y = 0;
    private static int a = 0,b = 0;

    public static void main(String[] args) throws InterruptedException {

        // 计数器
        int i = 0;
        for(;;){
            i++;
            // 重置
            a = 0;
            b = 0;
            x = 0;
            y = 0;

            // 闸门
            CountDownLatch countDownLatch = new CountDownLatch(1);

            // 线程一
            Thread one = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    a = 1;
                    x = b;
                }
            });

            // 线程二
            Thread two = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        countDownLatch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    b = 1;
                    y = a;
                }
            });

            two.start();
            one.start();
            // 放开闸门
            countDownLatch.countDown();
            // 主线程等待子线程执行完成
            one.join();
            two.join();

            String result = "第:"+ i +"次" + "(" + x + "," + y + ")";

            if(x == 0 && y == 0){ // 说明:如上代码出现x,y都等于0的情况说明代码执行时被重排序了(即代码并未按照编写顺序执行,而是被编译器重排序了其执行顺序大致为:y=a=0,x=b=0,b=1,a=1,)
                System.out.println("执行代码被重排序了:" + result);
                break;
            }else {
                System.out.println(result);
            }
        }
    }
}

执行结果

1.3.3.1.3.重排序好处

1.3.3.1.4.重排序的三种情况

        1.编译器优化;

        2.CPU指令重排;

        3.内存的“重排序”

1.3.3.2.可见性
1.3.3.2.1.什么是“可见性”问题

        可见性:指一个线程对共享变量的修改对于其它线程是可见的;

        可见性问题:多线程并发访问共享变量时,一个线程对共享变量的修改对于其它线程可能是不

                              可见的;

1.3.3.2.2.为什么会有“可见性”问题

因为CPU有多级缓存,导致某些线程读取到的数据可能已经过期;如果所有CPU核心都只用一个缓存,那就不存在可见性问题;而实际情况是每个核心都会将需要的数据读取到自己的“独占缓存”中,数据修改后也是先写入到自己的“独占缓存”,然后等待刷新到“主存”(所有核心共享)中,在数据还未被刷新到“主存”时造成其它核心读取到过期的数据值;

1.3.3.2.3.什么是happens-before

happens-before规则是用来解决“可见性”问题的,即在时间上动作A发生在动作B之前,B保证能看见A的所有操作这就是happens-before;

1.3.2.2.4.哪些运用了happens-before规则

        1.单线程规则;

        2.锁操作(synchroniezd和Lock);

        3.volatile变量;

        4.线程启动;

        5.线程join;

        6.传递性(hb代表happens-before; 如果hb(A,B),且hb(B,C)则可以推出hb(A,C)) ;

        7.中断(一个线程被其它线程interrupt,那么检测中断(IsInterrupted)或者抛出 

           InterruptedExcption一定能被其它线程看见);

        8.构造方法(对象构造方法的最后一条指令,finalize()方法一定能看到)

        9.工具类的happens-before原则

               9.1.线程安全的容器,如“ConcurrentHashMap”,get一定能看到之前的所有put操作;

                9.2.CountDownLatch

                9.3.Semaphore

                9.4.Future

                9.5.线程池

                9.6.CyclicBarrier

1.3.3.3.原子性
1.3.3.3.1.什么是原子性

     一系列操作,要么全部执行成功,要么全部不执行或全部执行失败,不会出现执行一半的情况,原子是不可分割的;

1.3.3.3.2.Java中的原子操作有哪些

1.除long和double之外的基本类型赋值操作(int,byte,boolean,short,char,float);

2.所有“引用”的赋值操作;

3.java.concurrent.Atomic.*包下所有类的原子操作;

备注:创建对象不是原子性操作!

1.3.3.3.3.long和double原子性问题

        对于32位的JVM long和double的操作不是原子的(32位JVM中会将long和double的一次写入操作拆分成2个单独的写入操作),但是在64位的虚拟机上long和double的操作是原子的,在实际开发中商用的Java虚拟机已经处理了这个问题;我们自己也可以使用volatile去解决;

1.3.3.4.原子操作 + 原子操作 != 原子操作

        简单地把原子操作组合在一起并不能保证整体依然具有原子性;

1.4.synchronized可见性的正确理解

1.4.1.synchronized不仅保证了原子性还保证了可见性;

1.4.2.synchronized不仅让被保护的代码线程安全,还让加锁之前的代码具有可见性;

1.5.面试题

1.5.1.单例模式的七种写法及单例和并发的关系

        详见:单例模式的七种写法URL

1.5.2.讲一讲什么是Java内存模型

        是一组规范,规范了JVM,CPU,JAVA代码之间一系列转换关系,Java内存模型最重要是“重排序”,“可见性”,“原子性”这三个部分(重排序讲1.3.3.1重排序的例子和重排序的好处),(可见性讲因为CPU有多级缓存JMM对内存抽象为“主内存”和“本地内存”,主内存是所有线程所共享的,本地内存是线程独占的其它线程访问不了。一个线程对变量的更改是先更新到本地内存中再同步到主内存中,其它线程只能在主内存中同步这个变量的值,因为本地内存同步到主内存是需要时间的这样就会导致一个线程在本地内存中已经更改了值而这个值还没有被同步到主内存中去,这样对于其它线程来说这个值的更改是不可见的,就会导致其它线程重主内存中拿到的值还是一个旧的值,这样就出现了“线程安全”问题,对于“可见性”来说还有一个happens-before原则即在时间上动作A发生在动作B之前,B保证能看见A的所有操作这就是happens-before; 再可以讲下1.3.2.2.4哪些运用了happens-before原则及再讲下volatie关键字volatile关键字),(最后可以再讲下1.3.3.3.2Java中的原子操作有哪些);

1.5.3.什么是原子操作?Java中有哪些原子操作?创建对象是原子操作吗?

        详见1.3.33原子性;

1.5.4.64位的double和long写入的时候是原子的吗?

        32位虚拟机上不是原子的,64位虚拟机上是原子的,实际开发中使用的商用Java虚拟机已经处理了这个问题不需要我们再考虑;

1.5.5.volatile和synchronized的异同

        详见volatile关键字;

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

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

相关文章

【powershell】Windows环境powershell 运维之历史文件压缩清理

🦄 个人主页——🎐开着拖拉机回家_Linux,大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁&am…

什么是文件包含漏洞?文件包含漏洞利用方法及防御技巧

文章目录 文件包含漏洞文件包含漏洞利用方法如何预防文件包含漏洞文件包含漏洞防御技巧网安学习路线 文件包含漏洞 文件包含漏洞是指在程序执行过程中,将外部文件的内容作为程序代码或数据的一部分来执行或使用,从而导致程序行为异常。攻击者可以利用文…

ansible的脚本---playbook剧本

ansible的脚本---playbook剧本 playbook组成部分 1、tasks任务:包含要在目标主机上执行的操作,使用模块定义这些操作,每个任务都是一个模块的调用 2、varlables变量:存储和传递数据,变量可以自定义,可以…

企业 NAS 升级,如何解决 Windows ACL 权限迁移和配置?

数字化转型是当前时代的必然趋势,它对于企业的创新能力和竞争力的提升至关重要。企业数字化发展过程中会产生大量的非结构化数据,旧有的存储已经不能完全满足企业需求。因此,相应的存储基础设施需要升级换代,以适应新的业务发展。…

本地生活团购外卖怎么做?一招教你轻易入行!

如果说今年生意不好做的话,那么年初做本地生活服务这个赛道的现在是喜忧参半。喜的是在本地生活干团购和外卖把钱给挣上了。忧的是官方清退了所有的全国本地生活服务商。通过官方渠道基本是没的玩了。本来还想着干个三五年。实现车子、房子、票子自由。这计划全落空…

【漏洞复现】Dedecms信息泄露漏洞(CVE-2018-6910)

Nx01 产品简介 DesdevDedeCMS(织梦内容管理系统)是中国卓卓网络(Desdev)科技有限公司的一套开源的集内容发布、编辑、管理检索等于一体的PHP网站内容管理系统(CMS)。 Nx02 漏洞描述 DesdevDedeCMS5.7版本中…

FA-238A (MHz范围晶体单元微型低轮廓SMD)

FA-238A是一款额定频率范围至12MHz~50MHz,工作温度和贮存温度范围-40℃~125℃,环境适应性强,频率老化率低至510-6/year(最大值,25℃),使用寿命长。FA-238A具有令人惊叹的紧凑外形尺寸&#xff0…

LeetCode 取经之路——第三题-无重复长度的最长子串

🎉🎉🎉今天给大家分享的是一道滑动窗口的OJ题。 3.无重复长度的最长子串 😛😛😛希望我的文章能对你有所帮助,有不足的地方还请各位看官多多指教,大家一起学习交流! 动动…

PropTypes 在 React 中的使用心得

在 React 开发中,PropTypes 是一个非常有用的库,用于对组件的属性进行类型检查。它可以帮助我们在开发过程中捕获潜在的错误,提高代码的可靠性和可维护性。本文将介绍 PropTypes 的基本用法和一些使用心得。 一、什么是 PropTypes PropTypes…

Python | Flask测试:发送post请求的接口测试

HTTP/1.1 协议规定的 HTTP 请求方法有OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 几种。POST通常用来向服务端提交数据,主要用于提交表单、上传文件。 HTTP 协议是以ASCII码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为…

Linux服务器 部署飞书信息发送服务

项目介绍: 飞书信息发送服务是指将飞书信息发送服务部署到一个Linux服务器上。飞书是一款企业级的即时通讯和协作工具,支持发送消息给飞书的功能。通过部署飞书信息发送服务,可以方便内网发送信息给外网飞书。 项目代码结构展示: …

Android Jetpack之用Room+ViewModel+LiveData实现增删改查数据(createFromAsset())

文章目录 一、Room简介二、用RoomViewModelLiveData增删改查数据三、下载源码 一、Room简介 Room是Google推出的数据库框架,是一个 ORM (Object Relational Mapping)对象关系映射数据库、其底层还是对SQLite的封装。 Room包含三个主要组件: 数据库类&…

软考学习五部曲

视频学知识 学习知识环节看视频看书都可以,书很厚一本。如果要看完的话要很多时间,所以我觉得还是看视频更快一点,而且视频还可以倍速。我看的那个视频我觉得非常不错,但是我看的视频b站已经下架了看不到了。其他的视频没仔细去看…

掀起全新的互联网直播风潮

随着科技的不断进步和智能手机的普及,无人直播作为一种全新的互联网直播方式,在近些年迅速崛起,并引起了广泛关注。本文将围绕手机无人直播展开探讨,探究其背后的原因以及对社会生活带来的影响。 首先,我们需要明确什…

商业银行数据资产估值白皮书,推荐系统源码下载

2022年12月2日,中共中央、国务院印发《关于构建数据基础制度更好发挥数据要素作用的意见》(以下简称“《数据二十条》”),指出要充分发挥海量数据规模和丰富应用场景优势,同时明确提出探索数据资产入表新模式。2023年8…

sql学习笔记(四)

1. 避免字段名与关键字冲突 1️⃣ 2️⃣ as 设置别名 2. 同比与环比 「同比」:与历史「同时期]比较,例如2011年3月份与2010年3月份相比,叫「同比」。 「环比」:与「上一个」统计周期比较,例如2011年4…

大数据HCIE成神之路之数据预处理(3)——数值离散化

数值离散化 1.1 无监督连续变量的离散化 – 聚类划分1.1.1 实验任务1.1.1.1 实验背景1.1.1.2 实验目标1.1.1.3 实验数据解析 1.1.2 实验思路1.1.3 实验操作步骤1.1.4 结果验证 1.2 无监督连续变量的离散化 – 等宽划分1.2.1 实验任务1.2.1.1 实验背景1.2.1.2 实验目标1.2.1.3 实…

macOS 安装 oh-my-zsh 后 node 报错 command not found : node

最近为了让终端中显示 git 分支的名称,安装了 oh-my-zsh ,安装之后呢,我原先安装的 Volta、 node 都没法用了,报错如下: 这时候粗略判断应该是系统变量出了问题,oh-my-zsh 的变量文件是 ~/.zshrc&#xff0…

Postman测试文件上传接口

文章目录 一、Postman测试文件上传接口1、创建一个请求→选择请求方式→填写请求的URL→填写请求的参数值2、选择 "Body" → "form-data" → "Test" → "File"3、点击 "Select Files"4、选择要上传的文件5、点击 Send 进行测…

解决 Hive 外部表分隔符问题的实用指南

简介: 在使用 Hive 外部表时,分隔符设置不当可能导致数据导入和查询过程中的问题。本文将详细介绍如何解决在 Hive 外部表中正确设置分隔符的步骤。 问题描述: 在使用Hive外部表时,可能会遇到分隔符问题。这主要是因为Hive在读…