内容简介:今天简单聊聊什么叫做 Java 内存模型,不是 JVM 内存结构哦。JMM 是一个语言级别的内存模型,处理器的硬件模型是硬件级别,Java中的内存模型是内存可见性的基本保证。从而为我们 volatile 实现内存可见性提供了基石。主要目的就是让 Java 程序员在各种平台下达到一致性访问效果
亲爱的读者朋友觉得文章不错点赞或关注公众号将是我最大的支持。欢迎关注公众号获取最新技术文章。
JavaStorm.png
今天简单聊聊什么叫做 Java 内存模型,不是 JVM 内存结构哦。
JMM 是一个语言级别的内存模型,处理器的硬件模型是硬件级别,Java中的内存模型是内存可见性的基本保证。从而为我们 volatile 实现内存可见性提供了基石。主要目的就是让 Java 程序员在各种平台下达到一致性访问效果
JMM决定一个线程对共享变量的写入何时对另一个线程可见 ,尤其是在对共享变量的读写,修改后其他线程立刻内读取到,这个就是JMM主要作用。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。Java内存模型的抽象示意如图所示。
image
前面我们说到 volatile 底层原理详解,这个语义的实现就是利用了Java的内存模型。为我们屏蔽了细节,实现了内存可见性,有兴趣的读者可以看公众号前期发的文章 volatile 底层原理实现 。
为什么需要JMM?
1. 从源代码到指令序列的重排序
在执行程序的时候,为了提高性能,编译器与处理器常会对指令进行重 排序 优化,保证执行结果与书序执行的结果是一致的,但并不能保证各个语句执行的先后顺序与输入的代码顺序一致。(当然是说在单线程的情况下)。
所以有 volatile 修饰的代码就不会被指令重排,相当于加了一道内存屏障,不能把后面的指令重排序到内存屏障之前。
2. Happens-before原则(先行发生)
Happens-before定义:
- 如果一个操作 Happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序在第二个操作之前。
- 两个操作之间存在 Happens-before 关系,并不意味着必须按照代码指定顺序执行。如果重排序后的执行结果与按照 Happens-before 结果执行的结果一致,那也是可以的。
先行发生是 Java 内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于B,其实就是说在发生操作 B 之前,操作 A 产生的影响能被 B 观察到, “影响” 包括修改了内存中共享变量的值、发送了消息、调用了方法。比如:
//在线程 A 执行 1 i = 2;` // 在线程 B 执行 2 j = i;` // 在线程 C 执行 3 i = 3; 复制代码
-
假设执行顺序是 1 -> 3 -> 2:那么 j 的值是 3。
-
假设执行顺序是 1 -> 2 -> 3:那么 j 的值是 2。
若我们想要按照 1 ,2 ,3顺序执行。那么只有同步才能保证一致性。
总而言之:
-
通过JMM内存模型,volatile 内存可见性的实现才得以保证。但是又不需要我们去关注不同平台的细节。当对一个 volatile 修饰的变量修改是,JMM 会把该线程对应的本地内存中的共享变量刷新到主内存中。
-
当读一个 volatile 变量的时候, JMM 会把该线程对应的本地内存设置无效,并从主内存中读取共享变量。
-
volatile 在满足 Happens-before原则情况下,禁止指令重排序。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- JVM内存模型 与 JMM内存模型
- C++11 中的内存模型(上):内存模型基础
- C++11 中的内存模型(下):C++11 支持的几种内存模型
- JVM内存模型解析
- golang内存模型
- 并发编程:内存模型
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Oricle8i Web开发指南
(美)Bradley D.Brown / 机械工业出版社 / 2001-6 / 78.00元
本书用实际通用的策略,阐明了怎样一起来看看 《Oricle8i Web开发指南》 这本书的介绍吧!