码字不易,欢迎大家转载,烦请注明出处;谢谢配合
主内存与工作内存
Java虚拟机规范试图定义一种Java内存模型(Java Memory Model,JMM
) 来屏蔽硬件和操作系统的内存访问的差异,以实现Java在不同平台都能达到一致的内存访问效果。
Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存以及从内存中取出变量的底层细节。
Java内存模型规定所有的变量都存储在主内存
,每个线程都有自己的工作内存
,线程的工作内存中保存着本线程使用变量的主内存数据副本;线程对变量的所有操作(读取,复制)都在工作内存中进行,不能直接在主内存中进行;并且线程之间是相互隔离的,一个线程不能访问其他线程工作内存的变量;线程之间的变量值传递都需要通过主内存来传递;可以参考以下示意图:
内存间交互
工作内存与主内存之间具体的交互协议,即具体的主内存复制到工作内存,工作内存同步到主内存的实现细节,Java内存模型定义了8种操作来完成:
-
lock
锁定
:作用于主内存的变量,它把变量标识为一个线程独占的状态 -
unlock
解锁
:作用于主内存的变量,它把一个锁定状态的线程释放出来,释放出来后的变量才能被其他线程锁定 -
read
读取
:作用于主内存的变量,它把一个变量的值由主内存传输到工作内存,以便后续load -
load
加载
:作用于工作内存的变量,它把read获取到的变量值放入到工作内存的变量副本中 -
use
使用
:作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用变量的字节码时会执行此操作 -
assign
赋值
:作用于工作内存的变量,它把从执行引擎获取到的变量值赋值给工作内存,每当虚拟机遇到变量赋值的字节码时会执行此操作 -
store
存储
:作用于工作内存的变量,它把工作内存的变量值传递给主内存,以便后续write操作使用 -
write
写入
:作用于主内存的变量,它把store操作从工作内存中获取的值,写入到主内存的变量中
Java内存模型同时还规定了8种操作必须满足以下规则:
1.read-load,store-write 指令,不能单独出现,并且还需要满足顺序性
2.线程变量assign后,必须同步给主内存
3.不允许无原因的进行同步操作,即没有工作内存执行assign操作,而发起向主内存的同步
4.新的变量只能在主内存中诞生
5.一个变量同一时刻,只允许一个线程lock
6.变量没有执行lock,不允许执行unlock
7.执行unlock前,必选先把变量值同步给主内存
8.lock变量时,会清除工作内存变量值,在执行引擎使用变量前要重新load或assign
基于理解难度与严谨性考虑JSR133文档中,已经放弃使用这8种操作去定义Java内存访问协议(描述方式改变了,内存模型没有改变)
happens-before 先行发生原则
happens-before 是Java内存模型保证多线程操作可见性的机制;它具体的表现形式包括我们但是不限于 synchronized、volatile、lock 操作顺序等方面;具体如下:
-
Programm Order Rule
程序次序规则 :在一个线程内,按照程序代码顺序,书写在前面的代码先行发生于书写在后面的操作 -
Monitor Lock Rule
管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作;这里强调是同一个锁 -
Volatile Veriable Rule
Volatile变量规则:对一个Volatile变量的写操作先行发生于后面对该变量的读操作 -
Thread Start Rule
线程启动规则:Thread对象的start()先行发生于该线程所有其他操作 -
Thread Terminal Rule
线程终止规则:线程所有的操作都先行发生于该线程的终止检测,我们可以通过Thread.join()方法结束,Thread.isAlive()的返回值检测到线程是否已终止 -
Thread Interruption Rule
线程中断规则:interrput方法的调用先行发生于该线程代码检测到中断事件发生,可以利用Thread.interrupted()检测是否有中断发生 -
Finalizer Rule
对象终结规则:一个对象的初始化先行发生于finlize()方法之前 -
Transtivity
传递性:如果A先行发生于B,B先行发生于C;那么A先行发生于C,具有传递性
- 本文链接: https://www.sunce.wang/archives/java-nei-cun-mo-xing
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!