Java虚拟机内存模型和volatile型变量
Java虚拟机内存模型
了解Java虚拟机的内存模型,有助于我们明白为什么会发生线程安全问题.

上面这幅图是<深入理解Java虚拟机-JVM高级特性与最佳实践>的书中截图.
线程共享的变量会保存在主内存中(Main Memory).
而线程共享的变量的副本会保存在每个线程各自的工作内存中(Working Memory).
线程对于共享变量的所有操作(读取,赋值等)都必须在工作内存中进行,不能直接读写主内存的变量.
不同的线程之间,也无法访问其他线程的工作内存.线程之间的变量传递需要通过主内存来完成.
所以发生线程安全问题的根源就在于,当共享变量在主内存中被修改后,有的线程的工作内存保存的还是该被修改的共享变量的旧的值,就导致了数据不一致的后果.
Volatile型变量
被Volatile修饰的变量,是轻量化的解决部分线程安全问题的方法,它具有2种特性:
1. 保证此变量对于所有线程的可见性,指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的.
但是这里所说的立即得知,也并不能保证Volatile就能完全避免线程安全数据一致的问题.
private volatile int race = 0;
private void increase() {
race++;
}
比如上面代码,如果多线程的调用increase()方法,是并不能保证线程安全,而且是很有可能发生数据不一致的问题.
原因在于,虽然volatile保证了race变量的修改被其他线程立即得知,但是本身race++这行代码并不是原子操作.实际代码编译后会变成多条字节码.
volatile的使用场景需要符合2条规则:
1) 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值;
2) 变量不需要与其他的状态变量共同参与不变约束.
volatile型变量的经典使用场景是如下这种.当doSomthing()方法被多线程调用时候,只需把shutDown=true之后,所有线程就不会在进行下一轮的while.
private volatile boolean shutDown = false;
private void doSomething() {
while (!shutDown) {
// do something
}
}
2. 使用Volatile变量能禁止指令重排序.
普通的变量仅仅会保证在该方法的执行过程中所有依赖赋值结果的地方都能获取到正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致.因为在一个县城的方法执行过程中无法感知到这点.
public VolatileExample {
Map configOptions;
char[] configText;
volatile boolean initiallized = false;
private void init() {
configOptions = new HashMap();
configText = readonfigFile(fileName);
processConfigOptions(configText, configOptions);
initialized = true;
}
private void do() {
while (!initialized) {
sleep();
}
doSomethingWithconfig();
}
}
上面这段代码,假设init()方法和do()方法运行再不同的线程中.如果initialized变量没有使用volatile修饰的话,init()方法可能由于指令重排序的优化(指令重排序是机器级的优化操作,提前执行时指这句话对应的汇编代码会被提前执行),导致最后一句代码initialized=true被提前执行.这种情况的后果就是do()方法因为initialized=true就跳过了while循环去执行doSomethingWithConfig()了,但其实可能init()的方法还未运行结束.
而volatile关键字可以避免此类情况的发生.
Java虚拟机内存模型和volatile型变量的更多相关文章
- Java线程角度的内存模型和volatile型变量
内存模型的目标是定义程序中各个变量的访问 规则,即在虚拟机中将变量(包括实例字段,静态字段和构成数组对象的元素,不包括局部变量与方法参数,因为后者是线程私有的)存储到内存和从内存中取出变量这样的底层细 ...
- 并发一:Java内存模型和Volatile
并发一:Java内存模型和Volatile 一.Java内存模型(JMM) Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和在内存中取出变量的底层细节,是围绕着 ...
- 黑马-----内存模型和volatile详解
黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...
- JAVA内存模型和Happens-Before规则
前言 上一篇文章王子给大家介绍了并发编程中比较关心的三个核心问题,可见性.有序性和原子性. 今天我们继续来探索并发编程的内容,聊一聊JAVA的内存模型和Happens-Before规则. JAVA内存 ...
- Java内存模型和JVM内存管理
Java内存模型和JVM内存管理 一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取 ...
- 【Java】JMM内存模型和JVM内存结构
JMM内存模型和JVM内存结构 JAVA内存模型(Java Memory Model) Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由JSR-133: JavaTM Memor ...
- Java 内存模型和 JVM 内存结构真不是一回事
这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...
- JVM内存结构、Java内存模型和Java对象模型
Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文要讨论的JVM内存结构.Java内存模型和Java对象模型 ...
- Java内存模型和ConcurrentHashMap 1.7源码分析
简介 ConcurrentHashMap 是 util.concurrent 包的重要成员.本文将结合 Java 内存模型,分析 JDK 源代码,探索 ConcurrentHashMap 高并发的具体 ...
随机推荐
- 20155333 2016-2017-2《Java程序设计》第二周学习总结
20155333 2016-2017-2<Java程序设计>第二周学习总结 教材学习内容总结 1. Java 类型系统:基本类型和类类型(参考类型) 2. 基本类型: 整数:short整数 ...
- 1135: [POI2009]Lyz
1135: [POI2009]Lyz https://lydsy.com/JudgeOnline/problem.php?id=1135 分析: hall定理+线段树连续区间的最大的和. 首先转化为二 ...
- 对posintion属性的简单认识,对于还在纠结的同学们,有一定的帮助
position的四个属性值: relative ,absolute ,fixed,static 下面分别讲述这四个属性,以简单代码表示 <div id="parent" ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)
最近接触过几个版本的cocos2dx,决定每个大变动的版本都尝试一下.本实例模仿微信5.0版本中的飞机大战游戏,如图: 一.工具 1.素材:飞机大战的素材(图片.声音等)来自于网络 2.引擎:coco ...
- 提取验证码到winform上webbroswer和axwebbroswer
在网上只有webbroswer的代码,所以自己又修改了修改改成axwebbroswer的 public static class yanZhengMaHelp { //webbrowser验证码 pu ...
- Python接口测试实战5(上) - Git及Jenkins持续集成
如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...
- JUC——ThreadFactory线程工厂类(四)
ThreadFactory线程工厂类 在默认情况下如果要想创建一个线程类对象,大部分情况的选择是:直接通过子类为父类进行实例化,利用Runnable子类为Runnable接口实例化. 或者直接调用La ...
- 解决webstorm中测试dva项目run start命令需要不断重启问题
用dva-cli构建了项目之后在webstorm开发,用npm start跑本地服务,经常修改之后在浏览器刷新没反应,偶尔才会有刷新,需要重新跑一遍npm start才会更新,这是怎么回事呢? web ...
- linux云主机小技巧
微信服务器安装 安装库 python 3.5环境下 pip安装web.py时 会报错 "no module named "utils" 等问题 更换命令为“pip ins ...
- Python基础灬异常
异常&异常处理 异常!=错误 在程序运行过程中,总会遇到各种各样的错误. 有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的 ...