jvm - 内存模型与线程
2017-08-25 00:00
183 查看
JVM 通过定义内存模型来屏蔽各种硬件和操作系统的内存访问差异,以实现让java程序在各平台都能达到一致的内存访问效果。
工作内存可以类比为CPU中的高速缓存。
主内存与物理硬件的主内存类比。
lock:作用于主存,标记线程独占。
unlock:作用于主存,释放锁定的变量。
read:作用于主存,将变量从主存读出,以便后续的load操作。
load:作用于工作内存,将read读取的变量副本放入工作内存。
use:作用于工作内存,将工作内存变量传给执行引擎。
assign:将执行引擎的值赋给工作内存。
store:作用于工作内存,从工作内存读出,传给主存,以便后续的write操作。
write:作用于主存,将store的值保存到主存。
规定上述操作必须满足如下规定:
不允许read和load、store和write单独出现。
不允许丢弃assign操作,即变量在工作内存改变后必须将变化同步到主存。
不允许无原因地将数据从工作内存同步到主存(没有assign操作)。
变量智能在主存中产生。也就是说对变量实施use、store操作之前,必须先执行assign和load操作。
一个变量允许被同一个线程多次lock,但同时需要相同次数的unlock。
如果对一个变量进行lock操作,那么会清空工作内存此变量的值,执行引擎执行之前必须重新load或assign初始化值。
对变量进行unlock之前,必须有对应的lock。
对变量进行unlock之前,必须把变量同步回主存。
由于volatile只能保证可见性,所有不符合以下两条规则的场景下,仍然需要通过锁来保证。
运算结果不依赖变量的当前值,或者能确保只有一个线程修改变量的值。
变量不需要与其他的状态变量共同参与不变约束。
第二个特征是禁止指令重排序优化。
volatile变量在use之前必须有前置操作read和load操作。
assign之后必须立即有store和write操作。
volatile变量与普通变量的区别是:volatile保证新值能立即同步到主存,以及每次使用前立即从主存刷新。
一下是天然的先行发生关系,无需任何同步就已经存在:
程序次序:在一个线程内,书写在前面的操作先行发生于书写在后面的操作。
管程锁定:unlock操作先行发生于后面对同一锁的lock操作。
volatile:一个volatile的写操作先行发生于这个变量的读操作。
线程启动:Thread的start()先行发生此线程的每个动作。
线程中断:线程interrupt()方法的调用先行发生于被中断代码检测到中断事件的发生。
对象的终结:一个对象初始化完成(构造函数执行结束)先行发生于它的finalize()。
传递性:A先行发生B,B先行发生C,则A先行发生C。
工作内存可以类比为CPU中的高速缓存。
主内存与物理硬件的主内存类比。
内存间交互
8中操作都是原子的(除了long、doubley允许例外)。lock:作用于主存,标记线程独占。
unlock:作用于主存,释放锁定的变量。
read:作用于主存,将变量从主存读出,以便后续的load操作。
load:作用于工作内存,将read读取的变量副本放入工作内存。
use:作用于工作内存,将工作内存变量传给执行引擎。
assign:将执行引擎的值赋给工作内存。
store:作用于工作内存,从工作内存读出,传给主存,以便后续的write操作。
write:作用于主存,将store的值保存到主存。
规定上述操作必须满足如下规定:
不允许read和load、store和write单独出现。
不允许丢弃assign操作,即变量在工作内存改变后必须将变化同步到主存。
不允许无原因地将数据从工作内存同步到主存(没有assign操作)。
变量智能在主存中产生。也就是说对变量实施use、store操作之前,必须先执行assign和load操作。
一个变量允许被同一个线程多次lock,但同时需要相同次数的unlock。
如果对一个变量进行lock操作,那么会清空工作内存此变量的值,执行引擎执行之前必须重新load或assign初始化值。
对变量进行unlock之前,必须有对应的lock。
对变量进行unlock之前,必须把变量同步回主存。
volatile
当一个变量定义为volatile后,具备两个特性,保证此变量对所有线程的可见性,这里的可见性指当一个线程改变了变量的值,新值对于其他程序是立即得知的。但并不是安全的,volatile变量也可以存在不一致的情况,但每次使用之前都要先刷新,执行引擎看不到不一致的情况,但是java的运算并不是原子操作(如++操作,对应多条字节码指令,每一条字节码指令有会对应多条机器指令)。由于volatile只能保证可见性,所有不符合以下两条规则的场景下,仍然需要通过锁来保证。
运算结果不依赖变量的当前值,或者能确保只有一个线程修改变量的值。
变量不需要与其他的状态变量共同参与不变约束。
第二个特征是禁止指令重排序优化。
volatile变量在use之前必须有前置操作read和load操作。
assign之后必须立即有store和write操作。
volatile变量与普通变量的区别是:volatile保证新值能立即同步到主存,以及每次使用前立即从主存刷新。
先行发生
如果说操作A先行发生于B,就是说发生在操作B之前,操作A产生的影响能被操作B观察到。一下是天然的先行发生关系,无需任何同步就已经存在:
程序次序:在一个线程内,书写在前面的操作先行发生于书写在后面的操作。
管程锁定:unlock操作先行发生于后面对同一锁的lock操作。
volatile:一个volatile的写操作先行发生于这个变量的读操作。
线程启动:Thread的start()先行发生此线程的每个动作。
线程中断:线程interrupt()方法的调用先行发生于被中断代码检测到中断事件的发生。
对象的终结:一个对象初始化完成(构造函数执行结束)先行发生于它的finalize()。
传递性:A先行发生B,B先行发生C,则A先行发生C。
相关文章推荐
- (一)线程------JVM体系结构与内存模型概要
- 图文详解jvm中的内存与线程模型
- JVM内存模型 - 主内存和线程独立的工作内存
- 简述JVM基础(七): Java 内存模型与线程
- Java多线程笔记一(创建运行,相关概念,JVM内存模型,线程有几种状态,死锁)
- jvm.内存模型与线程
- jvm 内存模型与线程 & Volatile
- 深入理解JVM-内存模型
- JVM并发机制探讨—内存模型、内存可见性和指令重排序
- jvm内存模型
- JVM内存模型简介
- 深入理解JVM(一)——JVM内存模型
- JVM内存模型学习(一、什么是内存模型)
- JVM内存模型及垃圾回收算法
- JVM学习之一.了解jvm的内存模型
- JVM内存模型及垃圾回收算法
- jvm内存模型
- 使用Jvisualvm监控JVM的内存、CPU、线程
- JVM线程执行模型简介
- JVM的线程内存模式与锁分析