Java并发编程-volatile可见性的介绍
要学习好Java的多线程,就一定得对volatile关键字的作用机制了熟于胸。最近博主看了大量关于volatile的相关博客,对其有了一点初步的理解和认识,下面通过自己的话叙述整理一遍。
有什么用?
volatile主要对所修饰的变量提供两个功能
- 可见性
- 防止指令重排序
本篇博客主要对volatile可见性进行探讨,以后发表关于指令重排序的博文。
什么是可见性?
一图胜千言
上图已经把JAVA内存模型(JMM)展示得很详细了,简单概括一下
- 每个Thread有一个属于自己的工作内存(可以理解为每个厨师有一个属于自己的铁锅)
- 所有Thread共用一个主内存(餐厅所有的厨师共用同一个冰箱)
- 每个Thread操作数据之前都会去主内存中获取数据(厨师炒菜之前都要去冰箱里拿食材)
- Thread:厨师
- 工作内存:铁锅
- store&load:放熟食,取食材
- 主内存:冰箱
读者可思考以下情景:
餐厅来了一位顾客点了一份红烧肉,此时有两位大厨(假设大厨之间互不通信),由于互不通信,所以两位大厨都打开冰箱取出食材开始炒菜。 最后炒出了两份红烧肉,顾客只要一份。为什么会造成这种结果?
由于大厨之间没有可见性。
将此情景放在JAVA中即是:
线程A从主内存中取了一个变量到工作内存中,操作完毕后没有及时放回主内存中,于是线程B去取这个变量已经 过期 了,取的是线程A操作之前的变量。
如何拥有可见性?
先介绍一下Java内存模型中定义的8种工作内存与主内存之间的原子操作
- lock( 锁定 ):作用于 主内存的变量 ,把一个变量标识为一条线程独占的状态。
- unlock(解锁):作用于 主内存 的变量,把一个处于锁定的变量释放出来,释放变量才可以被其他线程锁定。
- read(读取):作用于 主内存 的变量,把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
- load(载入):作用于***工作内存***的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
- use(使用):作用于***工作内***存种的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
- assign(赋值):作用于***工作内存***中的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
- store(存储):作用于***工作内存***的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用
- write(写入):作用于 主内存 的变量,它把store操作从工作内存中得到的值放入主内存的变量中。
读取赋值一个普通变量的情况
当线程1对主内存对象发起read操作到write操作套流程的时间里,线程2随时都有可能对这个主内存对象发起第二套操作
- 有什么危害呢?
假设主内存中有一个
int a=0;
线程1和线程2分别执行一次,理想状态下最终a的值为2.
a++;
线程1在执行了assign操作之后变量a的真实值已经从0变成了1,但是这个过程发生在工作内存中对其他线程不可见,若线程2此时对变量a的操作,读取到的值仍然为0,因为没有可见性,线程2的操作也仅仅是重复了线程1的操作,再次让a从0变成了1。 并没有达到期望的a=2。
读取赋值一个volatile变量的情况
- use之前不能被read&load
- assign之后必须紧跟store&write
也就是说 read-load-use 和 assign-store-write 成为了两个不可分割的原子操作
尽管这时候在use和assign之间依然有一段真空期,有可能变量会被其他线程读取,但是无论在哪一个时间点主内存的变量和任一工作内存的变量的值都是相等的。这个特性就导致了volatile变量不适合参与到依赖当前值的运算,如自增。 那么依靠可见性的特点volatile可以用在哪些地方呢? 《Java虚拟机》提到:
运算结果并不依赖变量的当前值(即结果对产生中间结果不依赖),或者能够确保只有单一的线程修改变量的值
通常volatile用做 保存某个状态 的boolean值。
Java并发编程-volatile可见性的介绍的更多相关文章
- Java并发编程 Volatile关键字解析
volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了 ...
- Java 并发编程——volatile与synchronized
一.Java并发基础 多线程的优点 资源利用率更好 程序设计在某些情况下更简单 程序响应更快 这一点可能对于做客户端开发的更加清楚,一般的UI操作都需要开启一个子线程去完成某个任务,否者会容易导致客户 ...
- Java并发编程volatile关键字
volatile理解 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和volatile 关键字机制.volatile具有synchronized关键字的“可见性”,vo ...
- Java并发编程--Volatile详解
摘要 Volatile是Java提供的一种弱同步机制,当一个变量被声明成volatile类型后编译器不会将该变量的操作与其他内存操作进行重排序.在某些场景下使用volatile代替锁可以减少 ...
- Java并发编程-线程可见性&线程封闭&指令重排序
一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...
- java并发编程 volatile关键字 精准理解
1.volatile的作用 一个线程共享变量(类的成员变量.类的静态成员变量等)被volatile修饰之后,就具有以下作用: 1)并发中的变量可见性(不同线程对该变量进行操作时的可见性),即一个线程修 ...
- Java并发编程-volatile
一. volatite 简述Java 语言提供了一种稍弱的同步机制,即 volatile 变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. ...
- java并发编程[持续更新]
目录 java并发编程 1.常用类介绍 Semaphore 2.名词解释 2.1 线程安全 2.2 可重入锁和不可重入锁 java并发编程 1.常用类介绍 Semaphore Semaphore 类是 ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
随机推荐
- C# 通过 Quartz .NET 实现Timer Job并将其注册成为Windows Service
之前的一篇文章讲述了如何通过 Quartz .NET 实现 Timer Job (http://www.cnblogs.com/mingmingruyuedlut/p/8037263.html) 在此 ...
- shiro登录密码加密
密码加密 String passwd = new SimpleHash("SHA-1", "username", "password").t ...
- ZOJ 2588 Burning Bridges 割边(处理重边)
<题目链接> 题目大意: 给定一个无向图,让你尽可能的删边,但是删边之后,仍然需要保证图的连通性,输出那些不能被删除的边. 解题分析: 就是无向图求桥的题目,主要是提高一下处理重边的姿势. ...
- CTSC2017总结
这个博客已经弃坑近一年了,自从去年国赛大力卡线进队后这近一年来我的情况从博客一年没更就可见一斑,OI水平原(zhi)地(xian)踏(fu)步(chong),炉石和双升的姿势水平倒是提高不少. 在经历 ...
- IOS8,IOS8.1等系统出现锁屏状态下WIFI断开问题的解决办法!
网络设备:TP-Link 300M无线路由器.DLINK 300M无线路由器.HP 300M无线路由器.APPLE AirPort无线路由器 终端:iphone5S+IOS8.1 故障现象:除appl ...
- http 缓存学习.
mark 一下 HTTP 缓存机制一二三 http://web.jobbole.com/92773/ 彻底弄懂HTTP缓存机制及原理 https://www.cnblogs.com/chenqf/p/ ...
- HTMl、CSS、JS的区别:
HTMl.CSS.JS的区别: Html:决定网页的结构和内容----[结构] Css:控制页面的表现样式,如:美化页面----[表现] Js:控制网页的行为,如:给页面加动态的效果----[行为]
- ubuntu 14.04 rabbitmq集群部署
1.准备机器,我这边准备的是三台ubuntu14.04 机器主机名不能相同,不然节点冲突 2.安装rabbitmq 3.修改hosts文件 root@abc-web-04:~# vim /etc/ho ...
- ztree设置节点checked,选中某节点等相关操作
ztree设置节点checked,选中某节点等相关操作 1.根据id获取树的某个节点: var zTree = $.fn.zTree.getZTreeObj("mytree"); ...
- 详解微信小程序开发(项目从零开始)
一.序 微信小程序,估计大家都不陌生,现在应用场景特别多.今天就系统的介绍一下小程序开发.注意,这里只从项目代码上做解析,不涉及小程序如何申请.打包.发布的东西.(这些跟着微信官方文档的流程走就好). ...