JAVA内存模型即JMM(Java Memory Model),有些人会和Java内存结构混淆。虽然两者名字很接近,但描述的为不同内容。Java内存结构描述的是JVM对内存的逻辑划分,我们在学习垃圾回收和JVM优化的时候会关心JVM内存结构。而本节所讲的JMM,实际上是一种规范。它描述了Java程序的运行行为,包括多线程操作对共享内存读取时,所能读取到的值应该遵守的规则。
JMM简介
JMM为程序中的所有操作定义了一定的规则,叫做Happens-Before。无论两个操作是否在同一个线程,如果要想保证操作A能看到操作B的结果,那么A、B之间一定要满足Happens-Before关系。如果两者间不满足Hapen-Before关系,JVM可以对其任意重排序。
当多个线程同时读写同一个变量,但这些操作间又没有满足Happens-Before关系,那么这些线程对此变量存在数据竞争,整个程序将会陷入混乱之中。假如我们在操作共享变量时采用了同步,那么无论有多少线程,对此变量的操作都会呈现出串行一致性。从而使得多线程的操作顺序遵守JMM约定。
Happens-Before规则
Happens-Before可以指导你如何开发多线程的程序,而不至于陷入混乱之中。你所开发的多线程程序,如果想对共享变量的操作符合你设想的顺序,那么需要依照Happens-Before原则来开发。happens-before并不是指操作A先于操作B发生,而是指操作A的结果在什么情况下可以被后面操作B所获取。下面我们就来看一下Happens-before原则。
1.程序顺序规则
如果程序中A操作在B操作之前,那么线程中A操作将在B操作前执行。
2.上锁原则
不同线程对同一个锁的lock操作一定在unclock前。
3.volatile变量原则
对于volatile变量的写操作会早于对其的读操作。
4.线程启动原则
A线程中调用threadB.start()方法,那么threadB.start()方法会早于B线程中中的任何动作执行。
5.传递规则
如果A早于B执行,B早于C执行,那么A一定早于C执行。
6.线程中断规则
线程interrupt()方法的一定早于检测到线程的中断信号。
7.线程终结规则
如果线程A终结了,并且导致另外一个线程B中的ThreadA.join()方法取得返回,那么线程A中所有的操作都早于线程B在ThreadA.join()之后的动作发生。
8.对象终结规则
一个对象初始化操作肯定先于它的finalize()方法。