Java内存模型与共享变量可见性(Java 工程师成神之路·基础篇·JVM)
2018-12-17 15:07
363 查看
1. Java内存模型(JMM)
- Java内存模型的主要目标:定义在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。
2. 内存模型就是一张图:
说明:
- 所有共享变量存于主内存
- 每一条线程都有自己的工作内存(就是上图所说的本地内存)
- 工作内存中保存了被该线程使用到的变量的主内存副本
注意:
- 线程对变量的操作都要在工作内存中进行,不能直接操作主内存
- 不同的线程之间无法直接访问对方的工作内存中的变量
- 不同线程之间的变量的传递必须通过主内存
类比:(注意:主内存与工作内存只是一个概念,与堆栈内存没有关系,下边的类比只是帮助理解)
- 主内存:对应于Java堆中的对象实例数据部分(注意:堆中还保存了对象的其他信息,eg.Mark Word、Klass
Point和用于字节对其补白的填充数据) - 工作内存:对应于栈中的部分区域
变量对所有线程的可见性
- 可见性:线程1对共享变量的修改能及时被线程2看到
共享变量不可见的原因
- 共享变量更新后的值没有在工作内存和主内存之间及时更新
- 线程交错执行
- 指令重排序结合线程交错执行
实现共享变量及时更新的措施
- 线程1修改过共享变量后,将共享变量刷到主内存,然后,线程2从主内存读取该共享变量,将该共享变量载入到工作内存中
- 注意:在短时间内的高并发情况下,如果发生下列三种情况,则线程2就读不到线程1修改过的最新的值了,
1.可能线程1根本来不及将修改过后的共享变量刷到主内存(这个时间非常短,但是还是有)的时候,线程2就已经读取了原有的主内存变量到其工作内存中。
2.可能线程1虽然将修改过后的值刷到了主内存中,但是线程2的工作内存中的变量副本还没来得及从CPU刷新回来,所以线程2读取到的还是原来的工作内存中的变量副本
3.可能线程1根本来不及将修改过后的共享变量刷到主内存的时候,同时,线程2的工作内存中的变量副本还没来得及从CPU刷新回来
注意:工作内存中的变量副本在使用之后,不会立刻消失掉,会一直存在,这样其值也一直不变,直到对其进行写操作或数据从CPU中刷新回来(类比volatile-read的作用)。
指令重排序:代码书写顺序与实际执行顺序不同(编译器或处理器为提高程序性能做的优化)
书写代码的顺序如下:
1 int a = 12; 2 int b = 13; 3 int c = a+b;
可能实际执行代码的顺序如下:
1 int b = 13; 2 int a = 12; 3 int c = a+b;
总结:本文大概介绍了一下Java内存模型以及与共享变量可见性的一些概念,为下边的volatile做准备。
本文转载自网络,如有侵权,请联系删除。 传送门:https://www.geek-share.com/detail/2663586623.html
相关文章推荐
- 附1 Java内存模型与共享变量可见性
- 附1 Java内存模型与共享变量可见性
- 【慕课网学习笔记】Java共享变量的可见性和原子性
- java工程师成神之路-基础篇
- Java保证共享变量“可见性”的机制
- 一、基础篇 1.1 JVM 1.1.1. Java内存模型,Java内存管理,Java堆和栈,垃圾回收
- JAVAWeb开发之Servlet-18.Servlet共享变量与变量的作用域
- Java工程师成神之路 转
- Java多线程编程:变量共享分析(Thread)
- java基础篇之常量,变量,数据类型和运算
- 在一个程序中需要用到全局变量(在多个class之间共享数据),请问如何定义具有这种功能的变量?或者是否有其他的方法解决多个class之间的数据共享(尽量简单实现)。 首先应该明确 Java中没有全局变
- JVM知识点总览-高级Java工程师面试必备
- JAVA 共享锁和条件变量一二
- 【java基础篇】——环境变量问题
- jvm系列(八):jvm知识点总览-高级Java工程师面试必备
- JAVA 并发编程-线程范围内共享变量(五)
- [Java 多线程] 变量可见性
- java环境变量 jdk jre jvm区别 java_home path设置 总结
- Java线程总结(四):ThreadLocal实现线程范围的共享变量
- Java关键字volatile,原子性,变量可见性