当前位置: 首页 > 后端技术 > Java

简单解释Java内存模型

时间:2023-04-02 01:39:30 Java

面试官:我记得我上次问为什么会有Java内存模型面试官:我记得你最后的回答是:为了屏蔽硬件和操作系统内存访问的各种差异,Java提出了“Java内存模型”的规范,保证了Java程序在各种平台上访问内存时都能得到一致的结果。内容?考生:嗯,在讲之前,我还是要强调一下:Java内存模型是一个“标准”,Java虚拟机实现了这个规范。考生:Java内存模型的主要内容,个人认为有以下几篇(后面会解释)面试官:那你从第一点说起?先说说Java内存模型的抽象结构?候选人:嗯。Java内存模型定义:Java线程与内存数据交互的规范。考生:线程之间的“共享变量”存储在“主内存”中,每个线程都有自己私有的“本地内存”,“本地内存”存储线程的副本,用于读/写共享变量。考生:本机内存是Java内存模型的抽象,并不真正存在。考生:顺便画个图,看图你就明白了。考生:Java内存模型规定线程对变量的所有操作都必须在“本地内存”中进行,而“不能直接读写主存”的变量考生:Java内存模型定义了8个操作来完成“如何实现”avariableFrommainmemorytolocalmemory,andvariableshowtogofromlocalmemorytomainmemory》候选:read/load/use/assign/store/write/lock/unlockoperation一次读写涵盖了这些操作,我会画另一张图告诉你候选人:明白了吗?无非就是读写中用到的各种操作(:面试官:明白了,很简单,happen-beforenext是什么?应试者:嗯,好吧(:应试者:按我的理解,happen-before其实就是它也是一套“规则”,Java内存模型定义这套规则的目的是为了解释“操作之间”的内存“可见性”候选者:上次讲“指令重排”时提到过,在两者的CPU中还有编译器存在指令重排的问题考生:虽然指令重排可以提高运行效率,但是在并发编程中,我们也希望“程序结果”能够由我们来控制。考生:说白了就是:在一些重要的场景下,这组操作是不能重排序的,“前一个操作的结果必须对后面的操作可见”。面试官:嗯……考生:所以,Java内存模型提出了一套规则,叫做happen-before。规则一共8条候选:比如传递性、volatile变量规则、程序顺序规则、监视器锁规则……(看规则的意思就知道,这个不难)考生:只要记住有像happen-before这样的规则。只要我们写的代码在这些规则下,前面操作的结果对后面的操作是可见的,就不会发生重排序。面试官:我明白你的意思面试官:那最后说说volatile吧?考生:嗯,volatile是Java中的关键字候选:为什么Java内存模型经常讲关键字volatile?我觉得主要是因为它的特点:visibilityandorder(禁止重排序)考生:Java内存模型的规范很大程度上就是为了解决visibility和order的问题。采访者:说说它的原理吧。volatile关键字是如何实现可见性和有序性的?Java内存模型定义了4种类型的内存屏障,以实现volatile的有序性和可见性。“标准”是LoadLoad/LoadStore/StoreLoad/StoreStore的候选者:回到volatile,说白了,就是在volatile前后加上“内存屏障”,让编译器和CPU无法重新排序,导致序列,并且写入volatile变量对其他线程可见。考生:Java内存模型定义了规范,那么Java虚拟机就得实现是吧?面试官:嗯……应聘者:之前看过Hotspot虚拟机的实现。在“汇编”层面,其实是通过Lock前缀指令实现的,而不是各种fence指令(主要是简单。因为大部分平台都是支持lock指令的,而fence指令是针对x86平台的)。考生:lock指令可以保证:禁止CPU和编译器的重排序(保证顺序),保证CPU写给内核的指令能立即生效,其他内核的缓存数据无效(保证可见性).面试官:那你提到这个,我想问下volatile和MESI协议有什么关系?候选人:他们没有直接关系。考生:Java内存模型侧重于编程语言层面,是一种高维抽象。MESI是一种CPU缓存一致性协议。不同的CPU架构是不同的。有的CPU可能根本就没有用MESI协议……考生:就是MESI名气大,所以大家都拿他举例。而MESI可能只在“特定场景”使用,实现volatile可见性/排序(:面试官:嗯...考生:为了让Java程序员屏蔽以上底层知识,快速入门使用volatile变量考生:发生-Java内存模型的规则之前有一个volatile变量规则的定义候选者:这条规则的内容实际上是:对一个volatile变量的写操作与后续对该volatile变量的写操作进行比较可见的读操作候选者:它由happen-before规则规定:只要变量声明了volatile关键字,写完再读,写的值必须是读可见的(可见性,有序性)面试官:嗯……明白了这篇文章总结:为什么会有Java内存模型:为了屏蔽硬件和操作系统访问内存的各种差异,Java提出了“Java内存模型”规范,保证了Java程序在各种平台上访问内存的一致性。作用Java内存模型抽象结构:线程间的“共享变量”存储在“主存”中,每个线程都有自己私有的“本地内存”,“本地内存”存储线程读写共享变量的副本多变的。线程对变量的所有操作都必须在“本地内存”中进行,变量“不能直接读写主内存”happen-before规则:Java内存模型规定在某些场景下(共8条),前面一个操作的结果必须对后面的操作可见。这8条规则就变成了happen-before规则volatile:volatile是Java中的关键字,修饰的变量可见且有序(不会重新排序)。可见性由happen-before规则完成,顺序由Java内存模型定义的“内存屏障”完成。实际的HotSpot虚拟机实现了Java内存模型规范,底层的汇编是通过Lock指令实现的。欢迎关注我的微信公众号【Java3y】说说Java面试,在线面试官系列持续更新中!【在线面试官-手机版】系列每周更新两期!【在线面试官-电脑】系列每周更新两期!原创不容易啊!!求三个链接!!