Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一个核心概念,它定义了Java程序中各种变量(线程共享变量)的访问规则,以及在并发环境下如何保证数据的一致性、原子性和可见性。JMM是围绕着原子性、可见性和有序性这三个概念来设计的。
Java内存模型有以下几个主要原则:
-
原子性原则:原子性是指操作要么执行,要么不执行,不会出现执行一半的情况。Java内存模型保证了基本类型的读取和赋值操作是原子的(除了long和double的非原子操作),如果要实现更大范围操作的原子性,需要通过同步代码块或锁来保证。
-
可见性原则:可见性是指当一个线程修改了共享变量的值,其他线程能够立即看到这个修改。在Java中,可以通过synchronized和volatile关键字来保证可见性。
-
有序性原则:有序性是指在本线程内,操作是按照代码的先后顺序执行的,但线程之间的操作可能会发生重排序。Java内存模型允许编译器和处理器对操作进行重排序,但是保证单线程内的指令执行是有序的。
-
happens-before原则:这是Java内存模型中的核心原则,它定义了两个操作之间的内存可见性关系。如果一个操作happens-before另一个操作,那么第一个操作对共享数据的所有改变都能被第二个操作观察到,且第一个操作必然在第二个操作前开始。
happens-before原则的规则
以下是happens-before原则的几条规则:
- 程序顺序规则:在一个线程内,按照代码顺序,前面的操作happens-before后面的操作。
- 监视器锁规则:对一个锁的解锁操作happens-before于随后对这个锁的加锁操作。
- volatile变量规则:对一个volatile变量的写操作happens-before于后续对这个变量的读操作。
- 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
- 线程启动规则:线程的start()方法happens-before于该线程中的所有操作。
- 线程终止规则:线程中的所有操作happens-before其他线程检测到这个线程已经终止。
- 中断规则:对线程的interrupt()方法的调用happens-before于检测到中断的事件发生。
- 对象finalize规则:一个对象的构造函数中的操作happens-before于finalize()方法的执行。
通过这些规则,JMM确保了在并发环境中,数据的正确性、可见性和有序性,从而为编写正确的并发程序提供了理论基础。理解happens-before原则对于编写无数据竞争的并发程序至关重要。