要学习好Java的多线程,就一定得对volatile关键字的作用机制了熟于胸。最近博主看了大量关于volatile的相关博客,对其有了一点初步的理解和认识,下面通过自己的话叙述整理一遍。

有什么用?

volatile主要对所修饰的变量提供两个功能

  • 可见性
  • 防止指令重排序

本篇博客主要对volatile可见性进行探讨,以后发表关于指令重排序的博文。

什么是可见性?

一图胜千言

 

上图已经把JAVA内存模型(JMM)展示得很详细了,简单概括一下

  1. 每个Thread有一个属于自己的工作内存(可以理解为每个厨师有一个属于自己的铁锅)
  2. 所有Thread共用一个主内存(餐厅所有的厨师共用同一个冰箱)
  3. 每个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变量的情况

 volatile变量对对象的操作更严格:
  • use之前不能被read&load
  • assign之后必须紧跟store&write

也就是说 read-load-use 和 assign-store-write 成为了两个不可分割的原子操作

尽管这时候在use和assign之间依然有一段真空期,有可能变量会被其他线程读取,但是无论在哪一个时间点主内存的变量和任一工作内存的变量的值都是相等的。这个特性就导致了volatile变量不适合参与到依赖当前值的运算,如自增。 那么依靠可见性的特点volatile可以用在哪些地方呢? 《Java虚拟机》提到:

运算结果并不依赖变量的当前值(即结果对产生中间结果不依赖),或者能够确保只有单一的线程修改变量的值

通常volatile用做 保存某个状态 的boolean值。

Java并发编程-volatile可见性的介绍的更多相关文章

  1. Java并发编程 Volatile关键字解析

    volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了 ...

  2. Java 并发编程——volatile与synchronized

    一.Java并发基础 多线程的优点 资源利用率更好 程序设计在某些情况下更简单 程序响应更快 这一点可能对于做客户端开发的更加清楚,一般的UI操作都需要开启一个子线程去完成某个任务,否者会容易导致客户 ...

  3. Java并发编程volatile关键字

    volatile理解 Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和volatile 关键字机制.volatile具有synchronized关键字的“可见性”,vo ...

  4. Java并发编程--Volatile详解

    摘要      Volatile是Java提供的一种弱同步机制,当一个变量被声明成volatile类型后编译器不会将该变量的操作与其他内存操作进行重排序.在某些场景下使用volatile代替锁可以减少 ...

  5. Java并发编程-线程可见性&线程封闭&指令重排序

    一.指令重排序 例子如下: public class Visibility1 { public static boolean ready; public static int number; } pu ...

  6. java并发编程 volatile关键字 精准理解

    1.volatile的作用 一个线程共享变量(类的成员变量.类的静态成员变量等)被volatile修饰之后,就具有以下作用: 1)并发中的变量可见性(不同线程对该变量进行操作时的可见性),即一个线程修 ...

  7. Java并发编程-volatile

    一. volatite 简述Java 语言提供了一种稍弱的同步机制,即 volatile 变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. ...

  8. java并发编程[持续更新]

    目录 java并发编程 1.常用类介绍 Semaphore 2.名词解释 2.1 线程安全 2.2 可重入锁和不可重入锁 java并发编程 1.常用类介绍 Semaphore Semaphore 类是 ...

  9. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

随机推荐

  1. Entitas Learning Document

    Entitas Learning Document You can find Entitas project in there Entitas for Unity Github There are a ...

  2. DevExpress控件库 开发使用经验总结2 DevExpress汉化之WinForm开发模式汉化

    2015-01-24 DevExpress控件库默认安装后,使用的本地资源为英文.Developer Express .NET产品都有本地化资源,比如按钮属性,控件属性描述,菜单项,确认和错误的信息等 ...

  3. 1.XGBOOST算法推导

    最近因为实习的缘故,所以开始复习各种算法推导~~~就先拿这个xgboost练练手吧. (参考原作者ppt 链接:https://pan.baidu.com/s/1MN2eR-4BMY-jA5SIm6W ...

  4. Cow Contest POJ - 3660 (floyd 传递闭包)

    N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we ...

  5. 【C语言编程练习】5.7填数字游戏求解

    之前的东西就不上传了,大致就跟现在的一样 1. 题目要求 计算 ABCD *  E DCBA 这个算式中每个字母代表什么数字? 2. 题目分析 如果是我们人去做这道题会怎么办,一定是这样想把,一个四位 ...

  6. 近期待学习&目标内容

    算法 Splay 树链剖分 AC自动机 问题 bzoj1010[HNOI2008]玩具装箱 bzoj1096[ZJOI2007]仓库建设 bzoj1597[USACP2008 Mar]土地购买 bzo ...

  7. 【安全性测试】利用反编译查看对应activity的方法采用hook技术绑定劫持_入门

    本次主要为了研究手机端的安全性而写的一篇文章,在基于自己对手机安全性的研究下,想到了这些工具之间的结合,当然这也算是第一次对手机安全研究勇敢地踏出一步,也不知道是否成功,还是准备撞南墙撞到底吧! 使用 ...

  8. 检查对象是否为NULL或者为Empty

    不管是在Winform开发,还是在asp.net 开发中当从一个数据源中获取数据时你总是不知道这个数据的状态,这个时候总要对她进行一次判断,不过每次进行一次判断总是要写怎么一堆代码,时间长了,总感觉不 ...

  9. hadoop常用操作命令

    #############centos6.8IP常用操作命令#######################DEVICE=eth0TYPE=EthernetONBOOT=yesNM_CONTROLLED ...

  10. java常用框架

    一.SpringMVC http://blog.csdn.net/evankaka/article/details/45501811 Spring Web MVC是一种基于Java的实现了Web MV ...