JVM知识(三):内存模型和可见性
这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况。来聊聊java线程对一个变量的更新怎么通知另一个线程,及volatile的作用和指令重排序的问题。
内存模型
首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做呢,又或者说,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象、数组元素都放在java堆中,java堆是共享的(这里我们把java堆称为主内存)。而每一个线程都是自己私有的内存空间(称为工作内存),如果线程1要向线程2通信,一定会经过以下类似的流程:
1、线程1将自己工作内存中的X更新为1并刷新到主内存中;
2、线程2从主内存中读取变量X=1,更新到自己的工作内存中,从而线程2读取的X就是线程1更新后的值。
从上面的流程看出线程之间的通信都需要经过主内存,而主内存与工作内存的交互,则需要java内存模型(JMM)来管理。下图演示了JMM如何管理主内存和工作内存:

当线程1需要将一个更新后的变量值刷新到主内存中时,需要经过两个步骤:
1、工作内存执行store操作(存储操作);
2、主内存执行write操作(写操作);
完成这两个操作即可将工作内存中的变量值刷新到主内存中,即线程1工作内存和主内存的变量值保持一致;
当线程2需要从主内存中读取变量的最新值时,同样需要经过两个步骤:
1、主内存执行read操作,将变量值从主内存中读取出来;
2、工作内存执行load操作,将读取出来的变量值更新到本地内存的副本;
完成这两步,线程2的变量和主内存的变量值就保持一致了。
可见性
java中有一个关键字 volatile,它有什么用呢?(没有volatile会出现的情况举例!)
这个答案其实就在上面说java线程间通信机制中,我们想象一下,由于工作内存这个中间层的出现,线程1和线程2比如存在延迟的问题,例如线程1在工作内存中更新了变了,但是还没有刷新到主内存,而此时线程2获取到的变量值就是还未更新的变量值,又或者线程1成功将变量更新到主内存,但是线程2依然使用主键工作内存中的变量值,同样会出现问题。不管出现哪种情况都可能导致线程间的同学不能达到预期的目的。
//线程1
boolean stop = false; while(!stop){ doSomething(); }
//线程2
stop = true;
这个例子表示线程2通过修改stop的值,来控制线程1的中断,但是在真是环境中可能会出现意想不到的结果,线程2在执行之后,线程1并没有立刻中断甚至一直不会中断。出现这种情况的原因就是线程2对线程1的变量更新无法第一时间获取到。
但是这一些等到volatile出现后,就不会出现了。volatile保证两件事情:
1、线程1工作内存中的变量更新会强制立即写入到主内存;
2、线程2工作内存中的变量会强制立即失效,这使得线程2必须去住线程中获取最新的变量值。
所以这就理解了volatile保证了变量的可见性。因为线程1对变量的修改能第一时间让线程2可见。
JVM知识(三):内存模型和可见性的更多相关文章
- JVM学习--(二)内存模型、可见性、指令重排序
我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再 ...
- JVM学习笔记——内存模型篇
JVM学习笔记--内存模型篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的内存模型部分 我们会分为以下几部分进行介绍: 内存模型 乐观锁与悲观锁 synchronized优化 内 ...
- [转帖]JVM—深入理解内存模型与垃圾收集机制
JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...
- (转载)JVM中的内存模型与垃圾回收
转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1 内存模型与运行时数据区 Java虚拟机在执行J ...
- 轻松学JVM(二)——内存模型、可见性、指令重排序
上一篇我们介绍了JVM的基本运行流程以及内存结构,对JVM有了初步的认识,这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存 ...
- 深入理解JVM(二)——内存模型、可见性、指令重排序
上一篇我们介绍了JVM的基本运行流程以及内存结构,对JVM有了初步的认识,这篇文章我们将根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况. 内存 ...
- 深入理解JVM一内存模型、可见性、指令重排序
一.内存模型 首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再把需求明确一点,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象.数组 ...
- 【JVM】JVM系列之内存模型(六)
一.前言 经过前面的学习,我们终于进入了虚拟机最后一部分的学习,内存模型.理解内存模型对我们理解虚拟机.正确使用多线程编程提供很大帮助.下面开始正式学习. 二.Java并发基础 在并发编程中存在两个关 ...
- 深入理解JVM(6)——Java内存模型和线程
Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...
随机推荐
- mongodb 数据库备份脚本
写了小shell bash, 用于给mongodb数据进行备份 #!/bin/bash #backup MongoDB #文件目录 #backup MongoDB #!/bin/bash #backu ...
- mysql查看权限的命令
mysql查看用户权限的命令 1.这里用来查看用户存储过程: show grants for 用户; eg: show grants for root@'localhost';#这样就会把root用户 ...
- lua热更框架之XLua
框架介绍 xLua是当下最流行的unity热更方案之一,作者是腾讯的车雄生前辈,自2016年初推出以来,已经在腾讯的多款游戏项目上应用,目前xLua已经开源到了GitHub.xLua最大的特色是不仅支 ...
- 12312312312312ssss
- visual studio 不能进入调试状态
解决Windows操作系统在处理回环地址 1. 第一种解决方案是禁用环回检查. 步骤如下 a) 依次单击“开始”和“运行”,键入 regedit,然后单击“确定” b) 在注册表编辑器中,找到并单击下 ...
- win7下使用IIS服务器及自定义服务器端包含模块(SSI)步骤
配置完过段时间就容易忘记,特此记录. 1.开启IIS服务器. 默认没有安装,需要先安装. 打开控制面板–> 打开“程序和功能”–> 左侧选择“启用或关闭windows功能”–> 找到 ...
- MySQL填坑系列--Linux平台下MySQL区分大小写问题
大家好,我是软件大盗(道),下面开始我们的<MySQL填坑系列>. 笔者最近又在MySQL的边缘试探,然后,试探着,试探着就报错了. 书接上文,系统连接数据库时报错:找不到DB_TIMIN ...
- Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
sudo chown -R username /usr/local/lib/node_modules 注:username要具有/usr/local/lib/node_modules的读写权限
- 二:java常用快捷键
ctrl+F6 切换编辑器 Ctrl+E 快速显示当前Editer的下拉列表 Ctrl+1 快速修复 Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Alt+Shif ...
- 一:idea中使用eclipse主题快捷键
idea -->file -->import settings -->keymap-shkstart.jar 1 执行(run) alt+r 2 提示补全 (Class Name C ...