初学者—JVM内存模型
一个java的线程里包含虚拟机栈,本地方法栈,程序计数器,堆,方法区。其中虚拟机栈,本地方法栈,程序计数器,线程独占。堆,方法区共享。

  • 程序计数器:记录当前虚拟机执行的字节码位置,程序执行的行号。

  • 虚拟机栈: 栈描述的是Java方法执行的内存模型每个方法被执行的时候都会创建一个栈帧存储着局部变量区,操作数栈,动态连接,方法的返回地址),栈帧里保存的的就是一个方法执行的必要参数和必要条件。每个方法从调用到执行完成,就是栈帧从入栈到出栈的过程。

    栈帧结构就好比一个方法,方法需要有返回值(对应返回值地址),需要有参数(对应局部变量区),里面需要有操作如if,for,system.out等,(对应操作数栈)在方法中创建对象的话需要有动态链接(对应动态链接) 。。

  • 本地方法栈:用来存放那些被native关键字标记的方法,其区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务,Navtive 方法是 Java 通过 JNI 直接调用本地 C/C++ 库,用来执行java不支持但是c语言支持的操作。

    JNI全称是Java Native Interface是在JAVA和Native层(包括但不限于C/C++)相互调用的接口规范。

  • 方法区(非堆):包含常量池和元数据区,最主要的就是放一些常量,用于存储被虚拟机加载的类型信息,如常量、静态变量、即时编译器编译后的代码缓存等数据。

元数据区和永久代的区别:

1.8以前叫永久代,1.8开始改为了元数据区
元数据区在物理内存中,永久代在JVM的虚拟内存中的。元数据区不存在内存溢出。

  • :堆用来存放对象实例,
    同时它也是GC所管理的主要区域,因此常被称为GC堆,又由于现在收集器常使用分代算法,Java堆中还可以细分为新生代和老年代,
指令重排序

1、指令重排序出现的原因:
因为cpu的运行速度比缓存速度快,为了提高运行时的效率,虚拟机会将指令按照自己的一些规则对指令进行重排序。指令重排序会引起的最终一致性不一致问题。优化cpu执行过程。

2、指令重排序发生的时期:
指令重排序分为两种,一种是编译重排序,一种是运行重排序,分别发生在JVM编译时期和CPU执行JVM字节码时期。

3、如何避免指令重排序:

指令重排序解决:1)内存屏障(cpu自带的)

​ 有两个作用:阻止屏障两侧指令重排序,强制把写缓冲区或高速缓存中的脏数据等写回内存,使缓存中的相应的数据失效

​ 2)在java中用内存屏障

​ 使用volatile(原子操作)去修饰变量(强制高速缓存的更新,高频率刷新)和 synchronize(变成同步)

volatile在低采样率的时候不会有问题,在高采样率的时候很小的几率会出现错误。

synchronized和volatile的区别:

synchronized是加同步锁,锁住后同时只有一个线程来操作,来保持最终一致性的。synchronized可以使用在变量、方法、和类级别,synchronized则可以保证变量的修改可见性和原子性

volatile是使高速缓存快速刷新,它可以同时有很多线程来操作,但是在操作的时候是通过高速刷新来保持一致性的volatile只能用于修饰成员变量和静态变量,且需要放在数据类型关键字之前。 volatile仅能实现变量的修改可见性,不能保证原子性;volatile` 和 final不能同时修饰一个变量。

volatile 和synchronize解决的都是一致性的问题

相关文章:

  • 2021-11-03
  • 2022-01-08
  • 2021-08-04
  • 2021-12-12
猜你喜欢
  • 2022-12-23
  • 2021-08-22
  • 2021-06-17
  • 2021-10-25
  • 2021-07-23
  • 2021-12-23
  • 2021-11-28
相关资源
相似解决方案