在多线程的并发编程中synchronized和volatile都扮演着重要的角色。volatile是轻量级的synchronized,它在多处理器的开发中保证了共享变量的可见性,可见性的意思是当一个线程修改一个共享变量时,另一个线程能够读取到这个修改值。如果volatile变量使用恰当的话,他会比synchronized的使用和执行成本更低。因为他不会引起线程上下文的调度和切换。本节将详细接收volatile的实现原理。

一.volatile的定义与实现原理

  Java语言规范第三版对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量可以被准确和一致的更新,线程应该确保使用排它锁单独获得这个变量。Java提供的volatile,在某些情况下比锁要更加的方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。

  在了解volatile实现原理之前,我们先来看下与其实现原理相关的CPU术语与说名。见下表:

术语 英文单词 术语描述
内存屏障  memory barriers  是一组处理器指令,用于实现对内存操作的顺序限制
缓冲行  cache line   缓存中可以分配的最小存储单元,处理器处理缓存线时,会加载整个缓冲线,需要使用多个主内存读周期
原子操作  atomic operations   不可中断的一个或则一系列操作
缓冲行填充  cache line fill  当处理器识别到从内存中读取的操作数是可缓冲的,处理器读取整个缓冲行到合适的缓存
缓存命中  Cache hit  如果进行高速缓存行填充操作的内存位置仍是下次处理器访问的地址时,处理器从缓存中读取操作数而不是从内存读
写命中  write hit  当处理器将操作数写回到一个内存缓存的区域时,它首先会检查这个缓存的内存地址是否在缓存行,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回内存,这个操作被称为写命中。
 写缺失  write miss the Cache  一个有效的缓存行被写到一个无效的内存区域

  volatile是如何来保证可见性的呢?让我们在X86处理器下通过工具获取JIT编译器生成的汇编指令来查看对volatile进行写操作时,CPU会做什么事情。

  Java代码如下:  

instance = new Singleton(); // instance是volatile变量

  转化为汇编代码后,如下:

0x01a3de1d: movb $0×0,0×1104800(%esi);
0x01a3de24: lock addl $0×0,(%esp);

  有volatile变量修饰的共享变量进行写操作的时候会多出第二行汇编代码,通过查IA-32架构软件开发者手册可知,Lock前缀的指令在多核处理器下会引发了两件事情:

  1.将当前处理器缓存行的数据写会到系统内存

  2.这个写会内存的操作会使在其他CPU里缓存了该内存地址的数据失效

  为了提高处理速度,处理器不直接和内存进行通信,而是将系统内存数据先读到内部缓存(L1,L2或则其他)后进行操作,但操作玩不知道何时会写会内存,如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条LOCK前缀的指令。将这个变量所在缓存行的数据写回到内存。但是就是写回到内存,加入其他CPU的的缓存还是旧的,再执行操作同样会有问题。所以在多处理下,为了确保各个处理器缓存的内容一致,就会实现缓存一致性协议,就是每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。
  volatile的两条实现原则

  1.Lock前缀指令会引起处理器缓存回写到内存

  2.一个处理器的缓存回写到内存会导致其他处理器的缓存无效

  

Java并发编程之volatile的应用的更多相关文章

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

    一内存模型的相关概念 二并发编程中的三个概念 三Java内存模型 四深入剖析volatile关键字 五使用volatile关键字的场景 volatile这个关键字可能很多朋友都听说过,或许也都用过.在 ...

  2. Java并发编程之volatile关键字

    大概是因为项目.业务的原因,工作上几乎还没有使用过多线程相关的功能,相关知识差不多都忘了,所以最近补一下基础. volatile用来修饰共享变量,volatile变量具有 synchronized 的 ...

  3. Java 并发编程之volatile关键字解析

    摘录 1. 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执 ...

  4. java并发编程之volatile

    Java语言规范第三版中对volatile的定义如下:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量. 了解volatile关键字之 ...

  5. Java并发编程之volatile变量

    volatile提供了弱同步机制,用来确保将变量更新通知到其它线程.volatile变量不会被缓存在寄存器中或者对其它处理器不可见的地方,因此在读取volatile变量时总会返回最新写入的值.可以想象 ...

  6. Java并发编程之CAS第一篇-什么是CAS

    Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...

  7. Java并发编程之CAS

    CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...

  8. Java并发编程之CAS二源码追根溯源

    Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...

  9. Java并发编程之CAS第三篇-CAS的缺点及解决办法

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

随机推荐

  1. 一名优秀的UI设计师应该具备哪些条件?

    想做好一个好的UI设计师除了应该具有一定的审美能力,还要了解整个产品的开发过程,因为目前国内的软件行业还不能对UI设计形成应有的重视度,所以对我们的要求就更高了,你要能作出夺人眼球的东西,还要站在用户 ...

  2. Ubuntu 网卡多个 IP 地址

    临时添加 IP 地址 首先,让我们找到网卡的 IP 地址.在我的 Ubuntu 15.10 服务器版中,我只使用了一个网卡. 运行下面的命令找到 IP 地址: 复制代码 代码如下: sudo ip a ...

  3. centos7 nginx 加入开机启动

    设置nginx开机启动 vi /etc/rc.d/init.d/nginx  #编辑启动文件添加下面内容 ############################################### ...

  4. input不能输入中文

    <input type="text" oninput="this.value = this.value.replace(/[\u4e00-\u9fa5d]/g, ' ...

  5. 2018.10.19 NOIP训练 桌子(快速幂优化dp)

    传送门 勉强算一道dp好题. 显然第kkk列和第k+nk+nk+n列放的棋子数是相同的. 因此只需要统计出前nnn列的选法数. 对于前mmm%nnn列,一共有(m−1)/n+1(m-1)/n+1(m− ...

  6. org.hibernate.HibernateException: /hibernate.cfg.xml not found等三个问题

    初次配置hibernate在myeclipse上: 出现三个问题,怎么都不好使,比对代码,没有问题,查看路径还是没有问题: 1.org.hibernate.HibernateException: /h ...

  7. Linux各个版本资源下载

    Linux系统各发行版镜像下载(持续更新) == Linux系统各发行版镜像下载(2014年10月更新),如果直接下载不了,请使用迅雷下载.并且注意,我的下载地址,在  迅雷 里才起作用. Linux ...

  8. POJ 2728 Desert King (最优比率树)

    题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目 ...

  9. HDU 5957 Query on a graph (拓扑 + bfs序 + 树剖 + 线段树)

    题意:一个图有n个点,n条边,定义D(u,v)为u到v的距离,S(u,k)为所有D(u,v)<=k的节点v的集合 有m次询问(0<=k<=2): 1 u k d:将集合S(u,k)的 ...

  10. Swift的Optional类型

    我们使用Swift这个苹果新推出的编程语言已经有一段时间了.其中的一个极大的优点就是苹果称为“optional types”的东西.几乎所有的objective-c程序员都知道用nil来表示某个引用类 ...