当前位置: 首页 > 科技观察

循序渐进了解什么是Java内存模型

时间:2023-03-20 10:40:06 科技观察

最近,笔者在看《深入理解Java虚拟机:JVM高级特性与最佳实现(第3版)》。书中提到了关于Java内存模型的知识点,但是看了之后还是觉得有些模糊,于是又查阅了一些其他的相关资料。这篇文章是作者对知识的理解和整理的总结。希望能帮助朋友们对Java内存模型有更清晰的认识。如果您对文章内容有其他的想法或建议,欢迎一起讨论,共同进步。下面将讨论以下三点:内存模型的由来内存模型的定义Java内存模型和内存模型的由来1.计算机执行程序时,每条指令都是CPU执行的。CPU在执行的时候为了获取数据,不可避免的要和主存打交道。2、随着CPU技术的发展,其执行速度越来越高。同时,由于内存技术发展缓慢,性能变化不大,所以每次CPU操作内存都需要一定的等待时间。时间。3、为了在保证CPU技术发展的同时优化解决这个问题,后来人们想出了一个解决方案,就是在CPU和内存之间加一个高速缓冲存储器(Cache)。高速缓存是介于主存和CPU之间的一级存储器。它由静态存储芯片(SRAM)组成。它的容量相对较小,但速度远高于主存,接近CPU的速度。在计算机存储系统的层次结构中,它是介于中央处理器和主存之间的高速小容量存储器。它与主存储器一起构成一级存储器。高速缓冲存储器和主存储器之间的信息调度和传输由硬件自动完成。因为Cache的速度接近于CPU的速度,CPU在每次对主存进行操作之前都会访问Cache,所以可以通过增加Cache来达到优化的效果。4、随着CPU的升级,一级缓存逐渐不能满足要求,于是逐渐衍生出多级缓存。存储在每一级缓存中的所有数据都是下一级缓存的一部分。CPU读取数据也演变为:当CPU要读取一段数据时,先从一级缓存中查找,如果没有找到,再从二级缓存中查找,如果仍然存在没有,它从下一级缓存开始查找,直到访问到内存。如下图5.单核CPU只包含一组L1、L2、L3缓存;如果CPU中包含多个核心,即多核CPU,每个核心都有一组L1(甚至L2)缓存,同时共享L3(或与L2)缓存,下图是单CPU双核缓存结构图:随着计算机能力的不断提高,开始支持多线程,那么可能会出现问题。下面分别分析一下单线程和多线程对单核CPU和多核CPU的影响。单核CPU单线程:核心缓存只被一个线程访问,缓存是独占的,不会出现访问冲突等问题。单核CPU多线程:一个进程中的多个线程会同时访问进程中的共享数据。CPU将一块内存加载到缓存中后,不同线程访问同一个物理地址时,会映射到同一个缓存位置,这样即使发生线程切换,缓存也不会失效。但由于任何时候都只能执行一个线程,因此不会出现缓存访问冲突。多核CPU和多线程:每个核心至少有一个L1缓存以提高效率。当多个线程在不同的核上执行,访问进程中的同一个共享内存时,由于多个核可以并行化,所以可能会出现类似多线程编程的并发问题,比如变量在同一块内存中,如果多个cores同时读、写、修改数据,会出现意想不到的错误,解决方法是通过锁机制。因此,在多核CPU、多线程场景下并发内存访问操作时,在CPU和主存之间加入缓存可能会造成歧义。处理器优化——“指令重排”除了上述问题,还有一个硬件问题也比较重要:处理器为了充分利用内部运算单元会进行优化,可能会乱序执行Enter代码,这里暂时理解为“指令重排”。除了一些处理器优化了代码的乱序处理,很多编程语言的编译器也有类似的优化。例如,Java虚拟机的JIT即时编译器也会进行指令重排。比如Java单例设计模式Double-Check例子中voliate关键字的应用,就是为了防止多线程并发场景下指令重排导致的异常。有兴趣的朋友可以参考我的另一篇深入分析单例模式的文章——懒人模式,这里就不多说了。什么是内存模型?上面这么多分析其实是为了引出两个重要的问题:多核CPU、多线程场景下并发内存访问操作可能会出现歧义。处理器将充分利用其内部计算单元。优化——“指令重排”那么如何解决以上问题呢?这时候引入了一个重要的概念——内存模型,其定义如下:内存模型是对内存读写访问过程的抽象,可以理解为内存模型定义了规范共享内存系统中的读写操作行为,并通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性。它与处理器有关,与缓存有关,与并发性有关,与编译器有关。目的是为了解决CPU多级缓存、处理器优化、指令重排等带来的问题和歧义,可以简单理解为内存模型其实是解决多线程场景下并发带来的问题的重要规范.Java内存模型1.定义Java内存模型(JavaMemoryModel,JMM)是一种内存模型规范,它屏蔽了各种硬件和操作系统的访问差异,使Java程序可以运行在各种平台上。实现一致内存访问效果的规范。2、理解Java内存模型(简称“JMM”)是一种规范,其主要目的是定义程序中各种变量的访问规则,围绕并发过程中如何处理原子性、可见性和顺序展开.特性来创建。关于Java内存模型的实现,相信熟悉Java并发编程的朋友应该不会陌生。Java提供了一系列与并发处理相关的关键字。其实这些都是Java的一些内存模型,在封装了底层实现之后,提供给程序员的。关键字,本文不会在这里一一讨论这些关键字,有兴趣的朋友可以看看《Java多线程编程核心技术》了解更多。比如使用volatile关键字解决指令重排带来的问题,使用synchronized关键字保证线程安全等等,其实都符合硬件在计算机内存模型中通过限制处理器优化和使用内存屏障来解决问题的方法..最后,本文从硬件可能出现的问题引出计算机内存模型的解决方案,进而提炼出多线程并发问题。最后介绍了Java内存模型。Java内存模型可以简单理解为围绕并发过程中如何处理原子性、可见性和顺序这三个特性而建立的一套规范,synchronized等关键字就是它的具体实现。