简单了解下JMM解决什么问题

点击合集可以查看往期文章。

什么是JMM

Java内存模型(JMM)是Java语言规范的一部分,定义了多线程环境下共享变量的访问规则。它解决了以下主要问题:

  1. 可见性:确保一个线程对共享变量的修改能够被其他线程看到。
  2. 原子性:保证某些操作的不可分割性。
  3. 有序性:避免由于编译器和处理器优化而导致的指令重排序问题。

JMM通过“happens-before”规则和内存屏障等机制,确保在多线程程序中,各线程对共享变量的操作行为符合预期。

CPU设计决定JMM设计

复杂的CPU设计需要设计Java内存模型(JMM)的原因包括:

  1. 指令重排序

    • CPU和编译器可能会对指令进行重排序以优化性能,这可能导致不同线程看到的操作顺序不一致。
  2. 缓存一致性

    • 多核CPU的每个核心可能有自己的缓存,JMM确保不同核心之间的缓存一致性,使得一个线程的修改能被其他线程看到。
  3. 内存屏障

    • 为了确保线程操作的正确顺序,需要在指令之间插入内存屏障。JMM定义了这些屏障的行为,确保内存操作的可见性和顺序性。
  4. 优化与并发

    • 现代CPU进行各种优化(如乱序执行),JMM提供了规则以保证这些优化不会破坏多线程程序的正确性。

复杂 CPU 设计

指令重排序

缓存一致性

内存屏障

优化与并发

可能导致操作顺序不同

确保多核缓存一致

定义内存操作顺序

保证优化不破坏正确性

CPU设计和JMM的联系

CPU设计和Java内存模型(JMM)在多线程程序中的角色虽然相关,但它们关注的层面和目标有所不同。

CPU设计

缓存一致性

指令重排序

内存屏障

多线程支持

硬件优化

缓存一致性协议

重排序规则

内存屏障机制

硬件同步机制

性能优化

JMM

可见性

原子性

有序性

这边整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

 需要全套面试笔记的【点击此处即可】免费获取

happens-before规则

线程间可见

操作的不可分割性

操作顺序保证

程序行为规范

与JMM的关系

硬件支持JMM

联系

  1. 多线程同步

    • JMM:定义了在Java程序中线程之间共享变量的可见性、原子性和有序性,确保多线程程序的正确性。
    • CPU设计:提供硬件支持,以确保不同线程间的操作一致性,可能通过缓存一致性协议、内存屏障等方式来实现。
  2. 内存一致性

    • JMM:通过“happens-before”规则确保线程操作的可见性和顺序性。
    • CPU设计:实现缓存一致性协议(如MESI协议)来保证不同核心或线程对内存的视图一致。
  3. 指令重排序

    • JMM:规定了编译器和处理器在执行线程操作时的行为,避免由于重排序导致的错误结果。
    • CPU设计:允许指令重排序以提高性能,并通过内存屏障和同步机制确保重排序不会破坏程序的正确性。

区别

  1. 关注层面

    • JMM:关注于Java程序中的线程间内存操作的语义,是一种抽象的内存模型,描述了Java虚拟机和程序员之间的行为规范。
    • CPU设计:关注于硬件级别的实现细节,如处理器架构、缓存管理、管道化等,是具体的硬件设计和优化。
  2. 实现方式

    • JMM:通过Java语言规范和Java虚拟机的实现来保证线程的正确性,不直接涉及硬件实现细节。
    • CPU设计:涉及具体的硬件设计和微架构实现,如缓存一致性协议、内存屏障等,以支持多线程操作的正确性和高效性。
  3. 抽象层次

    • JMM:在软件层面上定义行为,主要面向程序员和Java虚拟机的实现者,抽象了硬件的细节。
    • CPU设计:在硬件层面上定义操作,涉及具体的电路和硬件实现,直接影响性能和功能。

JMM带来的好处

JMM的设计作为一个统一入口,减少了开发工作量,包括兼容、性能这些都处理。

JMM的好处

提高程序的可移植性

保证多线程编程的正确性

便于开发人员理解和使用

优化性能

统一的内存模型

无需或少量修改

跨平台兼容

内存可见性

操作原子性

顺序一致性

同步机制

简化内存访问行为

易于理解同步机制

提高开发效率

优化锁竞争

合理使用 volatile

编译器和处理器优化

  • 提高程序的可移植性:由于 JMM 提供了一个统一的内存模型,Java 程序可以在不同的硬件平台和操作系统上无需修改或只需少量修改就能够正确运行。这大大提高了 Java 程序的可移植性,使得开发人员可以更加专注于业务逻辑的实现,而不必担心底层硬件的差异。
  • 保证多线程编程的正确性:JMM 定义了一系列规则来保证多线程环境下内存的可见性、原子性和有序性。这使得开发人员可以使用 Java 提供的同步机制(如 synchronized、volatile 等)来确保多线程程序的正确性,避免了由于硬件特性和编译器优化导致的难以调试的错误。
  • 便于开发人员理解和使用:JMM 提供了一个相对简单和直观的内存模型,开发人员可以更容易地理解多线程编程中的内存访问行为和同步机制。这有助于提高开发效率,减少错误的发生。
  • 优化性能:虽然 JMM 对内存访问进行了一定的限制,但同时也提供了一些优化的机会。例如,合理地使用 volatile 关键字和原子类可以避免不必要的锁竞争,提高程序的性能。此外,JMM 也允许编译器和处理器在不影响程序正确性的前提下进行一些优化,如指令重排序等,以提高程序的执行效率。

JMM的发展历程

  1. Java 1.0 和 1.1

    • 初期版本没有明确的内存模型,线程安全和同步的定义较为松散。
  2. Java 1.2

    • 引入了 synchronized 关键字和 volatile 变量,初步定义了多线程的基本同步机制。
  3. Java 1.5 (2004)

    • 引入了 Java 内存模型(JMM)的正式规范。增加了 java.util.concurrent 包,提供了更丰富的并发工具和原子变量。
    • 确立了 JMM 的基本规则,如 happens-before 关系、可见性、原子性和有序性。
  4. Java 1.6 到 1.8

    • 在 JMM 的基础上,增加了更多并发工具和优化机制,如 ConcurrentHashMap 和 ForkJoinPool
    • 对 JMM 进行了性能优化和补充,如加强了对编译器和处理器优化的支持。
  5. Java 9 到 11

    • 引入了新的特性如 CompletableFuture 和增强的 Stream API,进一步提高了并发编程的效率和简易性。
  6. Java 12 及以后

    • 持续优化和补充并发编程相关的特性和工具,如 Record 类型和 Pattern Matching,并不断调整 JMM 以适应新的编程模式。

JMM一直在不断发展以适应不同的设计和硬件。

  1. 进一步增强性能

    • 通过硬件支持和编译器优化,继续提高 JMM 在多线程环境下的性能表现。
  2. 适应新编程模型

    • 支持新兴的编程模型和并发模式,例如响应式编程和协程(轻量级线程)。
  3. 简化开发和调试

    • 提供更高层次的抽象和工具,以简化并发编程的开发和调试过程。
  4. 跨平台一致性

    • 确保 JMM 在不同硬件平台和 JVM 实现中的一致性,以提高跨平台的兼容性和可靠性。
  5. 增强文档和教育

    • 提供更全面的文档和教育资源,帮助开发者更好地理解和应用 JMM。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值