java内存模型(JMM)定义
来屏蔽各种硬件和操作系统的内存差异,以实现让java程序在各种平台都能达到一致的内存效果的模型。
主内存与工作内存关系
1.Java内存变量定义:包括实例字段,静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的。
2.主内存与工作内存关系:所有变量都存储在主内存,工作内存保存了主内存的副本拷贝
3.变量读取,赋值等操作都在工作内存中进行,不能直接读取内存变量。
主内存与工作内存交互流程
lock:作用于主内存变量,一个变量标识为被一条线程锁定的状态。
unlock:作用于主内存变量,释放锁,使变量可以被其他线程访问。
read:作用于主内存变量,把一个变量的值从主内存传输到工作内存。
load:作用于工作内存变量,把read的值放入工作内存。
use:作用于工作内存变量,把个在内存中的一个变量传递给执行引擎。
assign:作用于工作内存变量,把执行引擎接受到的值赋给工作内存变量。
store:作用于工作内存变量,把工作内存变量的值传递到主内存。
write:作用于主内存变量,把store的值放入工作内存。
volatile详解
volatile变量变量对所有线程可见,但是保证线程安全还需满足以下两个前提:
1.运算结果不依赖变量当前的值:不能保证线程安全的情况如static volatile int i=0;多个线程同时进行i++的操作时,无法保证线程安全,因为i++这部会执行getstatic和putstatic,在这个过程中其他线程会修改值;可以的情况如:static volatile boolean b = false;当多个线程设置b为true时,有一个线程设置完成后,其他线程马上能看到设置结果。
2.变量不需要与其他的状态变量共同参与不变约束。
volatile变量可以防止指令重排,如:
volatile b =false
线程A执行:
运行A的业务代码;
b = true
线程b观察 变量b是否true:
while(!b){
sleep();
}
运行b的代码。
如果不设置volatile,将有可能发生指令重排导致A中b=true发生在A的业务代码之前。导致b无法在A执行后执行。
原子性,可见性,有序性
原子性:每个java代码在执行指令时不受其他线程干扰,只做一部操作。
可见性:对一个变量赋值后这个操作结果其他线程也可见
有序性:线程内表现为“串行执行”,对于其他线程,因为指令重排和工作内存与主内存同步延迟的关系,有可能导致无序的现象。
先行发生原则
程序次序原则:按控制流程顺序进行
管程锁定规则:unlock发生在lock之前
volatile规则:volatile写操作由先与对其的读操作
线程启动规则:start()方法先发与线程的每个动作
线程中断规则:interrupt()优先于被中断的代码
线程终止原则:线程中所有代码优先于线程终止
对象终结规则:对象初始化先行与它的finalize()
传递性:a先与b,b先与c,推出a先与c