IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【Java并发底层原理精讲】JAVA内存模型-底层原理 -> 正文阅读

[Java知识库]【Java并发底层原理精讲】JAVA内存模型-底层原理

1. 到底什么叫"底层原理"?本章研究的内容是什么?

1.1 重要性

Java 面试的必考知识点。只有学会了这一章的内容,才能说你真正懂了并发。

1.2 从JAVA代码到CPU指令

在这里插入图片描述

1.最开始,我们编写的Java代码,是*.java文件

2.在编译( javac命令)后,从刚才的*.java文件会变出一个新的Java字节码文件( *.class)

3.JVM会执行刚才生成的字节码文件( *.class ) , 并把字节码文件转化为机器指令

4.机器指令可以直接在CPU上运行,也就是最终的程序执行

1.3 JVM实现会带来不同的“翻译”, 不同的CPU平台机器指令又千差万别,无法保证并发安全的效果一致

1.4 重点开始向下转移

转化过程的规范、原则

2. 三兄弟:JVM内存结构VS Java内存模型VS Java对象模型

2.1 整体方向

2.1.1 JVM内存结构:和JAVA虚拟机的运行时区域有关

在这里插入图片描述

堆(Heap):通过new或者其它方式创建的实例对象(包括数组)。如果这些对象不再被引用会被垃圾回收。的优势就是在运行时动态分配。

Java栈(VM stack):又称虚拟机栈,保存了各个基本数据类型,以及对于对象的引用。Java堆在编译时会确定大小,在运行时大小不会改变。

方法区(method):存储的是已经加载的各个static静态变量、类信息已经常量信息,还包含永久引用。

本地方法栈:保存的是和本地方法相关的信息;本地方法主要指native方法。

程序计数器:占用的区域是最小的,保存的是当前线程执行字节码的行号数,在上下文切换时,这个数据会被保存下来,包括需要下一条执行的指令、循环等异常处理。

2.1.2 Java内存模型,和Java的并发编程有关

2.1.3 Java对象模型,和Java对象在虚拟机中的表现形式有关,是对对象的抽象。

在这里插入图片描述

Java对象自身的存储模型

JVM会给这 个类创建-个instanceKlass ,保存在方法区,用来在JVM层表示该Java类。

当我们在Java代码中,使用new创建一个对象的时候 , JVM会创建一个instanceOopDesc对象,这个对象中包含了对象头以及实例数据

3. JVM是什么

Java Memory Model(JVM内存模型)

  • C语言不存在内存模型的概念。

  • 依赖处理器,不同的处理器结果不一样

  • 无法保证并发安全

  • 需要一个标准,让多线程的运行结果可预期

  • 规范

3.1 为什么需要JMM

需要各个JVM的实现来遵守JMM规范,以便开发者可以利用这些规范,更方便地开发多线程程序

如果没有这样的一个JMM内存模型来规范,那么很可能经过不同JVM的不同规则的重排序之后,导致不同的虚拟机上的运行结果不一样,那是很大的问题。

  • 是工具类和关键字的原理

volatile、synchronized、Lock等的原理都是JMM

如果没有JMM,那么就需要我们自己指定什么时候用内存栅栏等,那可是相当麻烦的,幸好有了JMM,让我们只需要用同步工具和关键字就可以开发并发程序。

  • 最重要的3点内容:重排序、可见性、原子性

4. 重排序

4.1 重排序的代码案例、什么是重排序

/**
 * 演示重排序的现象
 * */
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 {
        Thread thread1 = new Thread(()->{
           a = 1;
           x = b;
        });
        Thread thread2 = new Thread(()->{
            b = 1;
            y = a;
        });
        
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println( "x = " + x +",y = " + y);
    }
}

程序输出结果

x = 1,y = 0

Process finished with exit code 0

程序结果分析

赋值操作的4行代码的执行顺序决定了最终x和y的结果,一共有3总情况:

  • thread1先运行,a=1,x=b(0);b=1,y=a(1);,最终结果是x=0,y=1;
  • thread2先运行,b=1,y=a(0);a=1,x=b(1);,最终结果是x=1,y=0;
  • b=1;a=1,x=b(1);x=a(1),y=b(1);,最终结果是x=1,y=1;
/**
 * 演示重排序的现象
 * "直到到达某个条件才停止",测试小概率事件
 * */
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 count  =0;
       for (;;){
           count++;
           a = 0;
           b = 0;
           x = 0;
           y = 0;
           CountDownLatch latch = new CountDownLatch(1);
           Thread thread1 = new Thread(()->{
               try {
                   latch.await();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               a = 1;
               x = b;
           });
           Thread thread2 = new Thread(()->{
               try {
                   latch.await();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               b = 1;
               y = a;
           });

           thread2.start();
           thread1.start();
           latch.countDown();
           thread1.join();
           thread2.join();
           System.out.println("当前运行" + count + "次," + "x = " + x + ",y = " +y);
           if(x == 1 && y ==1){
               break;
           }

       }
    }
}

虽然代码执行顺序可能有很多种情况,但在线程1内部,也就是

a = 1;
x = b;

按照刚才的运行结果这两行代码的执行顺序是不会改变的,也就是a=1会在x=b前执行,同理,现在2的b=1;会在y=a;之前执行。因此无论如何也不会出现x=;y=0;的情况,但是真实情况会如此吗?

/**
 * 演示重排序的现象
 * "直到到达某个条件才停止",测试小概率事件
 * */
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 count  =0;
       for (;;){
           count++;
           a = 0;
           b = 0;
           x = 0;
           y = 0;
           CountDownLatch latch = new CountDownLatch(1);
           Thread thread1 = new Thread(()->{
               try {
                   latch.await();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               a = 1;
               x = b;
           });
           Thread thread2 = new Thread(()->{
               try {
                   latch.await();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               b = 1;
               y = a;
           });

           thread2.start();
           thread1.start();
           latch.countDown();
           thread1.join();
           thread2.join();
           System.out.println("当前运行" + count + "次," + "x = " + x + ",y = " +y);
           if(x == 0 && y ==0){
               break;
           }

       }
    }
}

程序输出结果

...
当前运行954,x = 1,y = 0
当前运行955,x = 1,y = 0
当前运行956,x = 0,y = 0

Process finished with exit code 0

程序结果分析

会出现x=0,y=0?那是因为发生了重排序,4行代码的执行顺序的其中一种可能是:

y=a;
a=1;
x=b;
b=1;

什么是重排序?在线程1内部的两行代码的实际执行顺序和代码在Java文件种的顺序不一致,代码指令不是严格按照语句顺序执行的,它们的顺序改变了,这就是重排序,这里被颠倒的是y=1;和b=1;这两行语句。

4.2 重排序的好处:提高处理速度

4.2 重排序的3种情况:编译器优化、CPU指令重排序、内存的"重排序"

5. 可见性

6. 原子性

7. 常见模式问题总结

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-27 10:57:09  更:2022-02-27 10:58:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:10:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码