登录 |  注册
首页 >  服务器/安全 >  Tomcat容器 从入门到精通学习笔记 >  深入理解Java内存模型(Java Memory Model,JMM)

深入理解Java内存模型(Java Memory Model,JMM)

Java内存模型(Java Memory Model, JMM)是Java语言规范的一部分,它定义了Java虚拟机(JVM)如何管理和协调各个线程之间的共享数据访问行为,旨在解决由于多线程环境下的数据可见性、原子性和有序性问题。理解和掌握JMM是编写高效、正确并发程序的关键。

一、Java内存模型概述

JMM主要关注的是程序执行时主内存与工作内存之间的关系。在JMM中,主内存是所有线程共享的数据区域,包含所有实例字段、静态字段和数组元素。而每个线程有自己的工作内存(本地内存),保存了该线程使用的变量副本。线程只能直接读写工作内存中的数据,不能直接读写主内存中的数据。线程间的通信必须通过主内存来完成。

二、JMM原理详解

Java内存模型的工作原理主要体现在主内存与工作内存的交互以及它们之间的数据同步机制上。线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

jmm.png

  1. 主内存与工作内存的交互 在JMM中,所有的共享变量都存储在主内存中,而每个线程都有自己的工作内存(本地内存)。线程对共享变量的所有操作都必须在工作内存中完成,不能直接读写主内存中的变量。线程对变量的操作分为以下几步:

    • read:从主内存读取变量的最新值到工作内存。

    • use:在工作内存中使用变量的值。

    • assign:在工作内存中给变量赋予新的值。

    • write:将工作内存中变量的新值刷新回主内存。

  2. 数据同步

    • 锁定(Lock):通过synchronized关键字或者显式锁对变量进行锁定,使得在同一时刻只能有一个线程对其进行读写操作,从而保证了原子性和可见性。

    • volatile关键字:修饰的变量强制任何对该变量的读/写操作都必须直接作用于主内存,且每次变量值变化都会使其他线程的工作内存失效,从而保证了可见性。另外,编译器和CPU不会对volatile变量进行不必要的重排序,一定程度上保证了有序性。

    • 内存屏障(Memory Barrier):**JMM通过插入必要的内存屏障来禁止特定类型的处理器重排序,确保数据的一致性和有序性。例如,volatile写操作会在前插入StoreStore屏障,后插入StoreLoad屏障,确保之前的写操作都完成并且此写操作的结果对其他线程立即可见。

  3. happens-before原则的实现 happens-before原则的背后是JMM通过内存屏障、锁机制以及volatile关键字提供的底层支持。这些机制确保了满足happens-before原则的两个操作之间,不仅存在执行顺序的约束,还保证了数据的可见性和一致性。

三、三大特性

  • 原子性(Atomicity) 原子性保证了基本的内存操作不可分割,要么全部执行成功,要么全部失败。但在Java中,并非所有的操作都是原子性的,例如long和double类型的变量赋值就不是原子操作。为了实现原子性,可以借助synchronized关键字、volatile关键字以及java.util.concurrent包下的原子类(如AtomicInteger)来实现。

  • 可见性(Visibility) 可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到这个更新。Java中通过volatile关键字来实现可见性,它能保证一个线程修改volatile变量后,其他线程可以立即看到新值。

  • 有序性(Ordering) 有序性指的是程序执行的顺序按照代码的顺序进行。但Java内存模型允许编译器和处理器为了优化重排序指令执行顺序,这可能导致多线程环境下出现乱序现象。Java提供了happens-before原则来保证有序性,通过synchronized、volatile和final等关键字可以创建happens-before关系。

四、happens-before原则

happens-before是JMM中最基础的法则,用来描述两个操作之间的内存可见性和时间先后顺序。简单来说,如果操作A happens-before 操作B,那么操作A的结果对于操作B是可见的,而且操作A在时间上的顺序发生在操作B之前。

例如:

  • 程序次序规则:在一个线程中,按照程序代码顺序,前面的操作happens-before后面的操作。

  • 监视器锁规则:对一个锁的解锁操作happens-before于随后对同一个锁的加锁操作。

  • volatile变量规则:对一个volatile域的写操作happens-before于任意后续对同一个volatile域的读操作。

  • 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

五、总结

Java内存模型通过对原子性、可见性和有序性的规定,为多线程编程提供了一个明确的理论基础。开发者在编写并发程序时,要充分理解和运用JMM的原理,合理利用synchronized、volatile等工具,才能确保程序在并发环境下表现出预期的行为,避免因内存模型带来的各种并发问题。同时,JMM也在不断发展和完善,例如Java 5之后对volatile的增强,使得它在保证可见性的同时还具备了一定的内存屏障效果。因此,紧跟Java内存模型的发展动向,也是编写高性能并发程序的重要一环。

上一篇: JMX 常见指标
推荐文章
  • Java内存模型(JavaMemoryModel,JMM)是Java语言规范的一部分,它定义了Java虚拟机(JVM)如何管理和协调各个线程之间的共享数据访问行为,旨在解决由于多线程环境下的数据可见性、原子性和有序性问题。理解和掌握JMM是编写高效、正确并发程序的关键。一、Java内存模型概述JMM
  • 为什么要设置静态IP在安装好CentOS虚拟机以后,一般我们会通过Xshell连接到虚拟机,而不是直接使用虚拟机里面的终端(Terminal)输入命令。如果使用默认的动态分配IP,虚拟机每次开机以后IP都会改变,Xshell连接需要修改IP。所以我们需要将IP设置成静态IP,只要虚拟机开机即可连接。
  • 使用centos的wget提示:commondnotfound是因为没有安装wget这个指令安装wgetyum -y install wget
  • 一、因为Centos官网是挂在国外的服务器上,下载镜像时相比于国内的下载速度会慢很多,所以在这里向大家分享两个国内的镜像站去下载Centos镜像。二、前往阿里云镜像站下载Centos7镜像1、阿里云官网地址:https://www.aliyun.com/ 2、点击左上角的【文档与社区】展开选择【镜像
  • 现在不管安防工程还是弱电工程,与网络的联系也越来越密切了,网络基础知识中的网络命令ping命令在项目中是使用频率最高的,一般我们用的都是它的基本功能,今天和大家来详细看下Ping命令的7个基础用法,掌握了秒变大神!1、ping命令基础2、ping-t的使用3、ping-a的使用4、ping-n的使用
  • 总结下工作中遇到的GC问题。一、JVM参数设置不当机器4G,部分JVM参数设置-Xmx3296m -Xms3296m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxGCPauseMillis=200 -XX:+Use
学习大纲