个人创作约定:本人声明所有文章均为原创,如有引用请注明出处任何文章,都会注明,如有疏漏,欢迎大家批评指正。如果您在网上发现有人抄袭本文,请举报并积极向本github仓库提交issue。感谢大家的支持~本文参考了很多文章、文档和论文,但是这个东西确实比较复杂,本人水平有限,可能理解不到位,如有异议,请留言。本系列会持续更新,在这里结合大家的问题和错误疏漏,欢迎大家留言。喜欢单体版的请访问:全网最硬核的Java新内存模型分析与实验单体版(持续更新在QA)全网hardcoreJava新内存模型——一、什么是Java内存模型全网最hardcoreJava新内存模型分析与实验——二、最硬核Java新内存的Atom访问与分词分析与实验全网内存模型-3.HardCoreUnderstandingMemoryBarrier(CPU+Compiler)全网最难的Java新内存模型分析与实验-4.Java新内存访问方式与实验最难的分析与实验-全网核心Java新内存模型-五、JVM底层内存屏障源码分析JMM相关文档:JavaLanguageSpecificationChapter17TheJSR-133CookbookforCompilerWriters-DougLea'sUsingJDK9MemoryOrderModes-DougLea的内存障碍、CPU和内存模型相关:弱内存模型与强内存模型内存障碍:软件黑客的硬件视图当代ARM和x86架构的详细分析内存模型=指令重新排序+存储原子乱序执行x86CPU相关信息:x86wikiIntel?64andIA-32ArchitecturesSoftwareDeveloperManualsFormalSpecificationofthex86InstructionSetArchitectureARMCPU相关资料:ARMwikiaarch64Cortex-A710Specification各种一致性的理解:CoherenceandConsistencyAleskey大神的JMM解释:AlekseyShipil?v-不要误解Java内存模型(上)AlekseyShipil?v-不要误解Java内存模型(下)相信很多Java开发都会用到Java中的各种并发同步机制,比如volatile、synchronized和Lock等,很多人也看过JSRChapter17Threads和Locks(地址:https://docs.oracle.com/javase/specs/jls/se17/html/jls-17.html),包括同步、Wait/Notify、Sleep&Yield、内存模型等,有做了很多Specification解释。但我也相信大多数人都和我一样。初读时,有种看热闹的感觉。清楚的认识。同时,结合Hotspot的实现和Hotspot源码的解读,我们甚至会发现,由于javac的静态代码编译优化和C1、C2的JIT编译优化,最终的性能代码与我们从规范中理解的不同。代码的行为可能不太一致。而且,这种不一致导致我们去学习Java内存模型(JMM,JavaMemoryModel),了解Java内存模型的设计。如果我们想通过实际代码来尝试,结果是我们可能正确的理解是有偏差的,导致误会。自己也在不断的尝试理解Java内存模型,重读JLS和各位大神的分析。本系列将从阅读这些规格和分析以及jcstress所做的一些实验中整理出一些理解。希望对大家理解Java9之后的Java内存模型和API抽象有所帮助。不过,我还是要强调一下,内存模型的设计是从抽象一些设计开始的,不关心底层。涉及的事情很多。本人水平有限,可能理解不到位。我会尽力解释每一点。所有的论点和参考文献都被提出来了。请不要完全相信这里的所有观点。如有异议,请具体举例反驳并留言。1.理解“Specification”和“Implementation”首先我想参考一下AlekseyShipil?v的理解思路,即首先分清Specification和Implementation的区别。前面提到的JLS(JavaLanguageSpecification)实际上是规范Java语言的规范,所有能够编译运行Java语言的JDK实现都必须实现其中规定的功能。但是对于实际的实现来说,比如HotspotJVM的JDK,就是一个具体的实现。从规范到实际实现其实是有一定区别的。首先是如下代码:HotSpot经过JIT优化和CPU指令优化后最终编译运行的实际代码其实是:将结果3放入寄存器并返回,这样效果就和原代码一致了,省略无用的局部变量操作,也是合理的。那你可能会有疑惑:不会吧,我这里断点运行的时候,能看到局部变量x,y,result。这实际上就是JVM在运行时所做的事情。如果您在DEBUG模式下运行JVM,默认情况下不会启用JIT。它会简单解释和执行,所以你可以看到局部变量。但是在实际执行中,如果这个方法是hot方法,经过JIT优化后,这些局部变量其实是不存在的。再比如Hotspot有一个锁扩展机制(后面会测试这个),即根据JLS的描述,x=1和y=1这两个操作是不能重排序的。但是Hotspot的实际实现会将上面的代码优化为:那么,其实x=1和y=1这两个操作是可以重新排序的,这个我们后面会验证。根据JVM实现的不同,实际性能会有所不同。并且即使实现了同一个JVM,在不同的操作系统、硬件环境等方面的表现也可能不一样。比如下面这个例子:一般情况下,r1的值应该只有两个结果中的一个{-1,0}。但是在一些32位的JVM上执行时会出现一些问题。比如在x86_32环境下,可能会有{-1,0,-4294967296,4294967295}这些结果。所以,如果我们想把底层完全覆盖到JMM设计、Hotspot实现、JIT优化等等,牵扯的东西太多了,一层层的逻辑和逻辑,我真的是面面俱到。而且我不能保证我的理解是100%准确的。如果我们想要涉及太多的HotSpot实现,那么我们可能会偏离我们系列的主题。其实我们主要关注的是Java自身的内存模型的设计规范,然后我们可以从中得出结论,在实际使用中需要了解和注意。点的最小集合,这也是本系列要梳理的。同时,为了保证本系列整理出的最小集合的准确性,会加入大量实际测试代码。也可以运行看看这里给出的结论以及对JMM的理解是否正确。微信搜索“我的编程喵”,关注公众号,微信添加作者,天天刷,轻松提升技术,领取各种优惠:我会经常发一些官方社区的各种框架的好消息视频资料和加个人翻译字幕到以下地址(含上公众号),欢迎关注:知乎:https://www.zhihu.com/people/...B站:https://space.bilibili。com/31...
