【干货】Java内存模型(JMM)(文本持续更新)

JMM前言

java内存模型,和并发编程有关(JMM—Java Memory Model)
是一组规范,需要各个jvm的实现来遵守jmm规范。

JMM结构

jmm包含五部分:
共有的:堆,方法区(static修饰对象)
私有的:栈,本地方法栈(native修饰),程序计数器

Java线程内存模型跟cpu的缓存模型类似,是基于cpu缓存模型来建立的。
所以结构组成:主内存—>多级缓存区—>工作内存

JMM必须要保证可见性、原子性、有序性
JMM遵循happens-before原则:第一个操作对于第二个操作是可见的。
可以使用volitale和synchronize解决。

Java内存模型只是一组规范,
Java 内存模型是个很复杂的规范,可以从不同的视角来解读,站在我们这些程序员的视角,本质上可以理解为,Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法。具体来说,这些方法包括 volatile、synchronized 和 final 三个关键字,以及六项Happens-Before 规则。

(可见性、原子性、有序性介绍)
原子性:原子性指的是一个操作不会被中断,操作不会受到其他线程的影响。两个线程同时对一个变量赋值,则该值要么是1要么是2,线程A和线程B互不干扰,不会被中断。
可见性:可见性指的是一个线程修改共享变量的值,其他线程能够马上得到这个修改的值。
有序性:序性指的是单线程中代码的执行总是按照循序执行的,多线程中可能出现乱序顺序,程序编译成字节码指令的时候可能会出现重排序现象,重排后的指令与原指令的顺序比一定一致。另一种角度:在一个线程内所有的操作都是有序的,但是在多线程下,一个线程观察另一个线程,所有的操作都是无序的,因为可能存在指令重排序和工作内存和主内存的同步延迟。编译器和处理器的重排序有编译器优化重排序,指令级并行重排序,即内存系统的重排序
在这里插入图片描述

JMM结构 以及运行流程

内存模型结构:
RAM:主存
cache:多级缓存区(每一层缓存的大小在缩小, 但读取速度在不断的增加,即L1最快缓存最少)
registers:寄存器(cpu通常从这获取数据)
线程的读写流程:
读:直接从寄存器中读取(如果被volatile修饰的变量,则直接从主内存读取)
写:写入主内存,并逐步缓存到各级缓存区以及寄存器之中。
在这里插入图片描述

volatile关键字

Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。
总结:
volitale不会缓存在寄存器以及其他处理器不可以见的地方,因此他直接从主内存进行读取。
volatile保证可见性和有序性,但是不保证原子性、保证原子性需要借助synchronized这样的锁机制

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值