当问到 Java 内存模型的时候,一定要注意,Java 内存模型(Java Memory Model,JMM)它和 JVM 内存布局(JVM 运行时数据区域)是不一样的,它们是两个完全不同的概念。
Java 内存模型存在的原因在于解决多线程环境下并发执行时的内存可见性和一致性问题。在现代计算机系统中,尤其是多处理器架构下,每个处理器都有自己的高速缓存,而主内存(RAM)是所有处理器共享的数据存储区域。当多个线程同时访问和修改同一块共享数据时,如果没有适当的同步机制,就可能导致以下问题:
Java 内存模型通过定义一套规则来规范并限制编译器、运行时以及处理器对内存访问的重排序行为,确保了多线程间的交互具有明确的语义。它规定了共享变量的访问规则、提供了 happens-before 原则以及 volatile 关键字、synchronized 等工具来实现内存可见性和一致性的保障。这样,程序员在编写并发代码时,可以依据这些规则来确保代码的正确执行,从而避免由于多线程带来的不确定性和错误。
如果没有 Java 内存模型就会出现以下两大问题:
具体内容如下。
要讲明白缓存一致性问题,要从计算机的内存结构说起,它的结构是这样的:
所以从上面可以看出计算机的重要组成部分包含以下内容:
当然,部分高端机器还有 L3 三级缓存。
由于主内存与 CPU 处理器的运算能力之间有数量级的差距,所以在传统计算机内存架构中会引入高速缓存(L2)来作为主存和处理器之间的缓冲,CPU 将常用的数据放在高速缓存中,运算结束后 CPU 再讲运算结果同步到主内存中,这样就会导致多个线程在进行操作和同步时,导致 CPU 缓存和主内存数据不一致的问题。
由于有 JIT(Just In Time,即时编译)技术的存在,它可能会对代码进行优化,比如将原本执行顺序为 a -> b -> c 的流程,“优化”成 a -> c -> b 了,但这样优化之后,可能会导致我们的程序在某些场景执行出错,比如单例模式双重效验锁的场景,这就是典型的好心办坏事的事例。
Java 内存模型(Java Memory Model,简称 JMM)是一种规范,它定义了 Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式,即规范了 Java 虚拟机与计算机内存之间是如何协同工作的。具体来说,它规定了一个线程如何和何时可以看到其他线程修改过的共享变量的值,以及在必须时如何同步地访问共享变量。
Java 内存模型主要包括以下内容:
Java 内存模型通过以上规则和语义,提供了一种统一的内存访问方式,使得多线程程序的行为可预测、可理解,并帮助开发者编写正确和高效的多线程代码。开发者可以利用 JMM 提供的同步机制(如关键字 volatile、synchronized、Lock 等)来实现线程之间的同步和通信,以确保线程安全和数据一致性。
内存模型的简单执行示例图如下:
为了更好的控制主内存和本地内存的交互,Java 内存模型定义了八种操作来实现(以下内容只需要简单了解即可):
happens-before(先行发生)原则是 Java 内存模型中定义的用于保证多线程环境下操作执行顺序和可见性的一种重要手段。
举个例子来说,例如 A happens-before B,也就是 A 线程早于 B 线程执行,那么 A happens-before B 可以保障以下两项内容:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。