Java 内存模型,许多人会错误地理解成 JVM 的内存模型。但实际上,这两者是完全不同的东西。Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何与我们的硬件内存进行交互的。而 JVM 内存模型,指的是 JVM 内存是如何划分的。
Java 内存模型,许多人会错误地理解成 JVM 的内存模型。但实际上,这两者是完全不同的东西。Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何与我们的硬件内存进行交互的。而 JVM 内存模型,指的是 JVM 内存是如何划分的。 Java 内存模型是并发编程的基础,只有对 Java 内存模型理解较为透彻,我们才能避免一些错误地理解。Java 中一些高级的特性,也建立在 Java 内存模型的基础上,例如:volatile 关键字。为了让大
在讨论Java内存模型之前,这里先一起聊聊CPU、高速缓存以及主内存,在了解这些知识后,对理解Java内存模型会有很大的帮助。
Java内存模型英文叫做(Java Memory Model),简称为JMM。Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性。
前几天,发了一篇文章,介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型,是这三个知识点当中最晦涩难懂的一个,而且涉及到很多背景知识和相关知识。
高并发编程-通过volatile重新认识CPU缓存 和 Java内存模型(JMM)
本文中,有很多定义和说法,都是笔者自己理解后定义出来的。希望能够让读者可以对Java内存模型有更加清晰的认识。当然,如有偏颇,欢迎指正。
计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。
本文转载自:https://www.hollischuang.com/archives/2550
下图简单的展示了最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存与高速缓存都连在系统总线上(BUS)这条总线同时还用于其他组件的通信:
首先我们在了解java内存模型之前先看一下计算机内存模型,理解了计算机内存模型的话后面在看JMM就会简单的多,上篇文章我是直接写的。
Java 内存模型跟上一篇 JVM 内存结构很像,我经常会把他们搞混,但其实它们不是一回事,而且相差还很大的,希望你没它们搞混,特别是在面试的时候,搞混了的话就会答非所问,影响你的面试成绩,当然也许你碰到了半吊子面试官,那就要恭喜你了。Java 内存模型比 JVM 内存结构复杂很多,Java 内存模型有一个规范叫:《JSR 133 :Java 内存模型与线程规范》,里面的内容很丰富,如果你没看过的话,我建议你看一下。今天我们就简单的来聊一聊 Java 内存模型,关于 Java 内存模型,我们还是先从硬件内存模型入手。
首先我们在了解java内存模型之前先看一下计算机内存模型,理解了计算机内存模型的话后面在看JMM就会简单的多。
CPU的频率非常快,主存Main Memory跟不上。CPU缓存是CPU与内存之间的临时数据交换器,为了解决CPU运行处理速度与内存读写速度不匹配的矛盾——缓存的速度比内存的速度快多了。
Java内存模型是在硬件内存模型上的更高层的抽象,它屏蔽了各种硬件和操作系统访问的差异性,保证了Java程序在各种平台下对内存的访问都能达到一致的效果。 Java内存模型是不可见的,它并不是一个真实的东西,它只是一个概念、一个规范。
通过上一篇《Java并发编程学习前期知识上篇》我们知道了在Java并发中的可见性是什么?volatile的定义以及JMM的定义。我们先来看看几个大厂真实的面试题:
Java内存模型是在硬件内存模型上的更高层的抽象,它屏蔽了各种硬件和操作系统访问的差异性,保证了Java程序在各种平台下对内存的访问都能达到一致的效果。
Java的内存模型定义了Java虚拟机如何和计算机物理内存进行交互。Java虚拟机是一体化的计算机模型,所以它自然也包含了内存模型。
客户端阻塞:如果客户端只有一个线程,这个线程发起读取文件的额操作必须等待IO流返回,客户端才能做其它事情。
面试者内心狂喜,这题刚背过:『Java内存主要分为五大块:堆、方法区、虚拟机栈、本地方法栈、PC寄存器,balabala……』
本篇文章将从计算机硬件、操作系统、Java语言,一环扣一环的引出Java内存模型存在的意义,让大家对Java内存模型(JMM)有较为深刻的理解。
多线程并发是Java语言中非常重要的一块内容,同时,也是Java基础的一个难点。说它重要是因为多线程是日常开发中频繁用到的知识,说它难是因为多线程并发涉及到的知识点非常之多,想要完全掌握Java的并发相关知识并非易事。也正因此,Java并发成了Java面试中最高频的知识点之一。本系列文章将从Java内存模型、volatile关键字、synchronized关键字、ReetrantLock、Atomic并发类以及线程池等方面来系统的认识Java的并发知识。通过本系列文章的学习你将深入理解volatile关键字的作用,了解到synchronized实现原理、AQS和CLH队列锁,清晰的认识自旋锁、偏向锁、乐观锁、悲观锁...等等一系列让人眼花缭乱的并发知识。
1、缓存是指将被频繁访问的热点数据存储在距离计算最近的地方,以方便系统快速做出响应。
今天我们讲一下java内存模型(JMM),JMM的问题在面试中经常被问到,我们今天就讲一下这道题.
####Java内存模型 Java内存模型描述了Java虚拟机和计算机内存之间是如何协同工作的。一个Java虚拟机也是一个完整的计算机的模型,因此,这个模型自然也包含了内存模型。
这几篇文章分别讲了 Java 内存模型、happens-before 原则、volatile 关键字、synchronized 关键字、Java 对象的内存布局。这 5 篇文章看着好像是独立的,但实际上他们是互相关联的。
其中 Runnable , ThreadPool 都是基于 Thread 执行的 ;
在单核计算机中,计算机中的CPU计算速度是非常快的,但是与计算机中的其它硬件(如IO、内存等)同CPU的速度比起来是相差甚远的,所以协调CPU和各个硬件之间的速度差异是非常重要的,要不然CPU就一直在等待,浪费资源。单核尚且如此,在多核中,这样的问题会更加的突出。硬件结构如下图所示:
最近,面试过很多Java中高级开发,问过很多次关于Java内存模型的知识,问完之后,很多人上来就开始回答:
Java 中的包装类(Wrapper Class)是为了将基本数据类型转换为对象而存在的。在 Java 中,每个基本数据类型都有对应的包装类,如 Integer、Double 等。
在多线程并发编程中synchronized和volatile都扮演着重要的角色。 volatile是轻量级的 synchronized,它在高并发中保证了共享变量的“可见性”。
在硬件中,为了解决处理器与内存的速度矛盾,在两者之间使用了高速缓存,但也引入了新的问题:缓存一致性。
相信很多 Java 开发,都使用了 Java 的各种并发同步机制,例如 volatile,synchronized 以及 Lock 等等。也有很多人读过 JSR 第十七章 Threads and Locks(地址:https://docs.oracle.com/javase/specs/jls/se17/html/jls-17.html),其中包括同步、Wait/Notify、Sleep & Yield 以及内存模型等等做了很多规范讲解。但是也相信大多数人和我一样,第一次读的时候,感觉就是在看热闹,看完了只是知道他是这么规定的,但是为啥要这么规定,不这么规定会怎么样,并没有很清晰的认识。同时,结合 Hotspot 的实现,以及针对 Hotspot 的源码的解读,我们甚至还会发现,由于 javac 的静态代码编译优化以及 C1、C2 的 JIT 编译优化,导致最后代码的表现与我们的从规范上理解出代码可能的表现是不太一致的。并且,这种不一致,导致我们在学习 Java 内存模型(JMM,Java Memory Model),理解 Java 内存模型设计的时候,如果想通过实际的代码去试,结果是与自己本来可能正确的理解被带偏了,导致误解。 我本人也是不断地尝试理解 Java 内存模型,重读 JLS 以及各路大神的分析。这个系列,会梳理我个人在阅读这些规范以及分析还有通过 jcstress 做的一些实验而得出的一些理解,希望对于大家对 Java 9 之后的 Java 内存模型以及 API 抽象的理解有所帮助。但是,还是强调一点,内存模型的设计,出发点是让大家可以不用关心底层而抽象出来的一些设计,涉及的东西很多,我的水平有限,可能理解的也不到位,我会尽量把每一个论点的论据以及参考都摆出来,请大家不要完全相信这里的所有观点,如果有任何异议欢迎带着具体的实例反驳并留言。
Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令。本章我们将深入底层一起探索下Java并发机制的底层实现原理。
Java内存模型深度解读 Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型。 如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的。Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。 原始的Java内存模型存在一些不足,因此Java内存模型在Java1.5时被重新修订。这个版本的Java内存模型在Java8中人在使用
volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在Java 5之后,volatile关键字才得以重获生机。
在java应用中,对于访问频率比较高,又不怎么变化的数据,常用的解决方案是把这些数据加入缓存。相比DB,缓存的读取效率快好不少。java应用缓存一般分两种,一是进程内缓存,就是使用java应用虚拟机内存的缓存;另一个是进程外缓存,现在我们常用的各种分布式缓存。相比较而言,进程内缓存比进程外缓存快很多,而且编码也简单;但是,进程内缓存的存储量有限,使用的是java应用虚拟机的内存,而且每个应用都要存储一份,有一定的资源浪费。进程外缓存相比进程内缓存,会慢些,但是,存储空间可以横向扩展,不受限制。
“ Java内存模型(Java Memory Model,JMM)的定义是Java虚拟机试图实现Java程序在各种平台下都能达到一致的内存访问效果。”
Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型。
左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存与高速缓存都连在系统总线上(BUS)这条总线还用于其他组件的通信 在高速缓存出现后不久,系统变得越来越复杂,高速缓存与主存之间的速度差异被拉大,直到加入了另一级缓存,新加入的这级缓存比第一缓存更大,并且更慢,而且经济上不合适,所以有了二级缓存,甚至是三级缓存
Java中为了线程通信的安全性(数据一致性),除了提供内置锁synchronized和显示锁ReentrantLock,还提供了另外一种线程同步机制——volatile,是一种轻量级同步机制。不过,通常很难轻易的理解volatile的真正意义。下面通过一个例子来认识一下volatile(摘自《深入理解Java虚拟机》):
volatile工作原理 java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。 Java语言提供了volatile,在某些情况下比锁更加方便。如果一个字段被声明成volatile,java线程内存模型确保所有线程看到这个变量的值是一致的。 若想清楚理解volatile关键字是如何保障共享变量在多线程之间正常使用的需要了解以下几点 java的内存模型 原子性,可见性,有序性 volatile的工作原理 测试case I. Java的内存模型
JVM 中试图定义一种 JMM 来屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。
目前计算机上会有多个CPU核心,我们可以创建多个线程,操作系统会将线程分配各不同的CPU去执行,如果只有一个线程,那么只会有一个CPU去工作,其他的CPU将会被浪费。
领取专属 10元无门槛券
手把手带您无忧上云