1、主内存与工作内存
Java内存模型的主要目的是定义程序中各种变量的访问规则,即关注在虚拟机中把变量值存储到内存和从内存中取出变量值这样的底层细节。此处的变量(Variables)与Java编程中所说的变量有所区别,它包括了实例字段、静态字段和构成数组对象的元素,但不是包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然也不会存在竞争问题。
Java内存模型规定了所有的变量都存储在主内存(Main Memory)中。每天线程还有自己的工作内存线程的工作内存中保存了该线程使用的变量的主内存的副本,线程对变量的所有操作,都必须在工作内存中进行,而不能直接读写主内存中的数据。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成,线程、主内存、工作内存三者的交互关系如下:
2、内存间的交互操作
(1)、lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
(2)、unlock(解锁):作用域主内存的变量,它把一个处于锁定状态的变量释放出来,释放后变量才可以被其他线程锁定。
(3)、read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
(4)、load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
(5)、use(使用):作用于工作内存的变量,它把工作内存中的一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
(6)、assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
(7)、store(存储):作用于工作内存的变量,它把工作内存中的一个变量的值传送到主内存中,以便随后的write操作使用。
(8)、write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入到主内存的变量中。
3、对于volatile型变量的特殊规则
当一个变量被定义为volatile之后,它将具备两项特性:第一项是保证此变量对所有线程的可见性。
使用volatile变量的第二个语义是禁止指令重排序优化。
4、先行发生原则
(1)、程序次序规则(Program Order Rule):在一个线程内,按照控制流顺序,书写在前的操作先行发生于书写在后面的操作。
(2)、管程锁定规则(Monitor Lock Rule):一个unlock操作先行发生于后面对同一个锁的lock操作。
(3)、volatile变量规则(Volatile Variable Rule):对一个volatile变量的写操作先行发生于后面对这个变量的读操作。
(4)、线程启动规则(Thread Start Rule):Thread对象的start()方法先行发生于此线程的每一个动作。
(5)、线程终止规则(Thread Termination Rule):线程中所有的操作都先行发生于对此线程的终止检测。
(6)、线程中断规则(Thread Interruption Rule):对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生。
(7)、对象终结规则(Finalizer Rule):一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始。
(8)、传递性(Transitivity):如果操作A先行发生于操作B,操作B先行发生于操作C,那就可以得出操作A先行发生于操作C的结论。