`
scanfprintf123
  • 浏览: 79192 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Volatile语义的一些探讨

阅读更多

  好吧,这里我只想说说volatile在JMM中的语义。

 

  当我们在使用volatile的时候,实际上它表达了下面那么些意思。

 

   1. 可见性。

      这个是大多数人都知道的一个特质, JAVA的线程有自己的工作内存区,与主存区不同,当我们对变量使用了volatile后,那么不管对这个变量的读或写,都会在主存中进行,而不会在处理器的缓存或者寄存器中进行。这个很好理解。

 

 

   2. 禁止CPU指令的重排序

      这个特质的理解稍微要花点脑细胞, 首先我们需要一点premilinary, 当我们的程序编写好了以后,会被翻译成指令集并被加载到内存中去运行。但是,在CPU真正执行的时候,处于性能方面的考虑,这些指令的执行不一定会按照程序中的顺序进行,只要保证其程序执行语义没有变化即可。

 

     来看下代码,

class VolatileExample {
  int x = 0;
  volatile boolean v = false;

  //in thread A
  public void writer() {
    x = 42;
    v = true;
  }

  //in thread B
  public void reader() {
    if (v == true) {
      //uses x - can we see x is 42?
    }
  }
}
 

    在这种情况下,当thread A 执行完后,在thread B中能看到x等于42吗?(变量v肯定可以看到,根据可见性可以推断出来) 好吧,在旧的JMM模型下,答案是不一定。原因就是CPU指令在执行时的重排序。在旧的JMM模型下,只规定了volatile变量和volatile变量之间不能进行重排序,但是并没有保证volatile变量和non-volatile变量之间不能进行重排序,所以, 当在thread A中,指令的执行可能是:

 

v = true;
x = 42;

 这样,当thread B 看到v为true的时候,x实际上还没有执行,所以值不是42.

 

 

   慢!眼尖的同学可能看出来了, 你说的这个跟重排序实际上没有关系呀,这个应该算是变量x的可见性问题,因为变量x不是声明为volatile的。

 

   好吧,我承认我偷懒了,在描述volatile变量可见性特质的时候,在新的JMM模型下,当对volatile变量进行写的时候,该线程(这里是thread A)所能看到变量(比如说变量x),都会一起刷新到主存中。这个也就是为什么我们会说对volatile变量的写操作,实际上等价于使用了synchronized关键字后释放monitor时产生的效果。 在这个前提下,上面的问题的确是CPU指令重排序的问题。

 

   但是幸运的是,JMM随后提出了happen-before原则来fix了这个问题(主要是volitale变量和non-volatile变量之间的重排序问题。)

    这里我只挑跟这个问题相关的三条原则来进行讲解,其余的可以到官方文档去查看。

 

    1. 单线程原则, 在单线程执行的环境下,指令的执行是跟程序代码的执行顺序一致。 对于上面的例子来说,在程序代码顺序上,x=42 先于 v=true, 那么在内存指令执行的时候也是如此。

 

    2. volatile变量原则,对volatile变量的写操作要优先于对volatile变量的读操作。

    3. 转递性原则,如果A操作先于B操作,B操作先于C操作,那么A操作肯定先于C操作。

 

    还是上面的例子,先用单线程原则,可以判断出,在thread A的执行中, x=42肯定要优先于v=true进行执行, 而在thread B的执行中,对v的读取操作肯定要优先于对x的使用操作。

    接着再使用volatile变量原则,可以判断,对v的写肯定要先于对v的读, 最后再根据转递性原则, 可以推出在thread A中x=42的赋值操作肯定要先于thread B中对x的使用, 也就是说,当v读取出来是为true的时候,x肯定是42. 指令不会进行重排序。

 

那如果我们将x=42,v=true的语句倒过来呢?

 

class VolatileExample {
  int x = 0;
  volatile boolean v = false;
  public void writer() {
    //颠倒赋值给x,v的顺序。
    v = true;
    x = 42;
  }

  public void reader() {
    if (v == true) {
      //uses x - can we see x is 42 here?
    }
  }
}
 

我想通过上面的分析,各位同学自己应该也能推断出来了吧。:)

 

 

0
3
分享到:
评论
2 楼 nurenok 2016-06-17  
1. 单线程原则, 在单线程执行的环境下,指令的执行是跟程序代码的执行顺序一致。 对于上面的例子来说,在程序代码顺序上,x=42 先于 v=true, 那么在内存指令执行的时候也是如此。

对于这个我也有疑问?很难确保把
1 楼 hobitton 2011-09-26  
有点疑问:
引用
1. 单线程原则, 在单线程执行的环境下,指令的执行是跟程序代码的执行顺序一致。 对于上面的例子来说,在程序代码顺序上,x=42 先于 v=true, 那么在内存指令执行的时候也是如此。


这个原则貌似没有见过呢?指令的执行顺序受编译器,JIT的影响,如果编译过程中进行了重排序,那么这段代码不可能知道运行的时候是否是单线程执行环境,那么这个原则就不对了吧?

相关推荐

    Volatile详解,深入学习Volatile

    详细说明 并举例说明了VOlatile的作用及用法,特别是嵌入式程序员要注意的

    java volatile 关键字实战

    java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...

    java多线程volatile内存语义解析

    主要介绍了java多线程volatile内存语义解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    volatile用法

    c语言下关键字的volatile用法,包含一些基本例子

    C语言中关键字volatile的作用

    C语言中关键字volatile的作用,使用说明和例子

    const和volatile分析

    const和volatile分析 这个分析得很好 面试 找工作 必备的

    从汇编角度理解volatile

    一般对于volatile的解释是这样的:将变量定义为volatile可以防止编译器对变量进行优化,每次均从内存中访问变量,而不是寄存器。既然让编译器优化可以提高访问速度,那为什么又要不用它以及什么时候不用它?其实主要...

    volatile的用法讲解

    volatile的用法讲解,讲得很详细,希望能帮助到大家

    volatile的使用

    一般说来,volatile用在如下的几个地方: 1、中断服务程序中修改的供其它程序检测的变量需要加volatile; 2、多任务环境下各任务间共享的标志应该加volatile; 3、存储器映射的硬件寄存器通常也要加volatile说明,...

    Java线程:volatile关键字

    主要讲述java线程volatile关键字

    volatile的用法

    volatile的用法,在写代码正确使用volatile,正确理解volatile的用法,增强代码的健壮性

    volatile变量详解

    容易忽略的变量声明,但是很重要 volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

    volatile的使用方法

    C程序中volatile关键字的使用.方法及其例程介绍。

    volatile与synchronized的区别

    volatile与synchronized的区别,锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)

    volatile_unsigned_int

    讲述了volatile_unsigned_int地址映射的使用说明。

    volatile源码分析1

    前言Java中volatile这个热门的关键字,在面试中经常会被提及,在各种技术交流群中也经常被讨论,但似乎讨论不出一个完美的结果,带着种种疑惑,准备从JVM、

    static,const,volatile用法

    static,const,volatile用法的解析,对三项中全局变量和局部变量的区分,volatile中介绍了其具体用法 和一些区别,bong有例子

    深入探讨Java多线程中的volatile变量共6页.pd

    深入探讨Java多线程中的volatile变量共6页.pdf.zip

    单片机C语言中volatile的作用

    本文给大家介绍了单片机C语言中volatile的作用。

    const,extern,static,volatile的使用

    const,extern,static,volatile的使用

Global site tag (gtag.js) - Google Analytics