JMM(Java内存模型)中的核心概念

时间:2021-08-08 20:50:21

JMM(Java内存模型)中的核心概念
guibin.beijing@gmail.com

在JLS-Java Language Specification的17.4节详细描述了JMM(Java Memory Model),这个文档从语言学和实现JVM的角度讲非常棒,但是对于我们这些应用开发者而言理解其中的细节就有些问题。

本文中不再重复spec中那些正式的细节,下面将列出一些重要的原则和基本的概念,如synchronizes-with,happens-before。这两个概念和面向对象设计中的两个概念has-a,is-a很相似,Happens-before 和 synchronizes-with是用来建立和理解Java 并发的基础。

HAPPENS-BEFORE:这个关系用来指示“一段代码在其他代码开始执行前已经完全执行完毕”。
SYNCHRONIZES-WITH:这个关系表示一个行为在发生时,它首先把要操作的那些对象同主存同步完毕之后才继续执行。

JMM有以下主要的规则:
An Unlock operation on a monitor synchronizes-with later lock operations. 当针对一个监控对象执行解锁操作时,首先synchronizes-with随后的锁操作。即当要解锁时,首先此操作会把它范围内的对象与主存同步,然后解锁,之后才会执行随后其他的锁操作。
A write to a volatile variable synchronizes-with later reads of the variable. 当写一个volatile变量时,首先synchronizes-with随后的读此变量的操作。即当写完一个volatile变量后,JVM会首先将此变量与主存同步,然后才执行随后的读volatile变量操作。当然也从主存读了。
If an action A synchronizes-with action B, then A happens-before B. 如果时行为A synchronizes-with 行为B,那么行为A happens-before B。
If A comes before B in program order within a thread, then A happens-before B. 在同一个线程中如果程序中A在B之前,那么A也一定发生在B之前。
The completion of a constructor happens-before the finalizer for that object starts to run. 完成构造函数会发生在此对象的finalizer启动之前,即在对一个对象回收前,此对象必须已经构造完毕。
An action which starts a Thread synchronizes-with the first action of the new Thread. 创建了一个新线程的行为synchronizes-with这个线程的第一个操作。即创建完新线程后,JVM首先要把这个线程的信息同步给主存,然后才可以执行这个线程内部的其他操作。
Thread.join() synchronizes-with the last (and all other) actions in the thread being joined. Thread.join()函数synchronizes-with被join的线程内部的所有其他操作。即执行Thread.join()之后JVM首先会把信息跟主存同步,然后才会继续执行被join线程内部的其他操作。
(Transitivity) If X happens-before Y, and Y happens-before Z, then X happens-before Z. 传递性,即X在Y之前执行,Y在Z之前执行,那么X会在Z之前执行。

前面的两条规则是说:“releases happen before acquires;” (解锁发生在获取锁之前)即:一个线程拿着锁,当写操作完毕后首先释放锁,然后这个锁才能被其他线程获得

以上的这些规则是JMM所做的基本保证,在真正的JVM实现中会有更多更好的规则。