目录
Java 内存模型(Java Memory Model,JMM)
1. 定义和目的
2. 内存结构
3. 三大特性
4. happens-before 原则
内存屏障(Memory Barrier)
1. 定义和作用
2. 分类
3. 在 Java 中的应用
Java 内存模型(Java Memory Model, JMM)
1. 核心概念
2. 内存交互规则
3. 可见性
4. 有序性
5. 原子性
内存屏障(Memory Barrier)
1. 作用
2. 类型
3. 在 Java 中的应用
4. 示例
总结
Java 内存模型(Java Memory Model,JMM)
1. 定义和目的
Java 内存模型(JMM)是 Java 虚拟机规范中定义的一种抽象概念,它屏蔽了各种硬件和操作系统的内存访问差异,保证了 Java 程序在不同的硬件和操作系统平台上都能达到一致的内存访问效果,主要目的是为了确保多线程程序中数据的可见性、原子性和有序性,从而避免出现数据竞争和不一致的问题。
2. 内存结构
JMM 将内存分为主内存和工作内存:
- 主内存:是所有线程共享的内存区域,存储了所有的共享变量,如实例变量、静态变量等。
- 工作内存:每个线程都有自己独立的工作内存,线程对共享变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接操作主内存中的变量。线程在工作内存中会拷贝一份主内存中共享变量的副本,操作完成后再将结果刷新回主内存。
3. 三大特性
- 原子性:指一个操作是不可中断的,要么全部执行成功,要么全部不执行。在 Java 中,对基本数据类型的变量的读取和赋值操作是原子性的,但像
i++
这种复合操作不是原子性的。可以使用synchronized
关键字或Atomic
类来保证操作的原子性。 - 可见性:当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。由于线程有自己的工作内存,可能会导致一个线程修改了共享变量的值,但其他线程没有及时从主内存中读取到最新的值。可以使用
volatile
关键字、synchronized
关键字或Lock
来保证可见性。 - 有序性:程序执行的顺序按照代码的先后顺序执行。但在 Java 中,为了提高性能,编译器和处理器可能会对指令进行重排序。重排序分为编译器重排序、指令级并行重排序和内存系统重排序。JMM 提供了
happens-before
原则来保证部分有序性,同时可以使用volatile
关键字和synchronized
关键字来禁止特定类型的重排序。
4. happens-before
原则
happens-before
原则是 JMM 中定义的一些规则,用于判断两个操作之间的执行顺序。如果操作 A happens-before
操作 B,那么操作 A 的结果对操作 B 是可见的,并且操作 A 会在操作 B 之前执行。常见的 happens-before
规则有:
- 程序顺序规则:一个线程中的每个操作,
happens-before
该线程中任意后续操作。 - 监视器锁规则:对一个锁的解锁,
happens-before
随后对这个锁的加锁。 volatile
变量规则:对一个volatile
域的写,happens-before
任意后续对这个volatile
域的读。- 传递性:如果 A
happens-before
B,且 Bhappens-before
C,那么 Ahappens-before
C。
内存屏障(Memory Barrier)
1. 定义和作用
内存屏障,也称为内存栅栏,是一种 CPU 指令,用于控制特定条件下的重排序和内存可见性问题。在 JMM 中,内存屏障是实现 volatile
、synchronized
等关键字语义的基础。其主要作用有两个:
- 禁止指令重排序:编译器和处理器为了提高性能,可能会对指令进行重排序,但在某些情况下,重排序会影响程序的正确性。内存屏障可以告诉编译器和处理器在内存屏障前后的指令不能进行重排序,保证指令按照特定的顺序执行。
- 保证内存可见性:内存屏障可以强制刷新处理器的缓存,使得一个线程对共享变量的修改能够及时被其他线程看到。当一个线程执行写操作