Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。
而volatile关键字就是提示JVM:(这就是volatile的
原理)对于这个成员变量不能保存它的私有拷贝(在线程栈),而应直接与共享成员变量(在主存中)交互。
(打个广告,有兴趣的童鞋可以去看看
http://hellosure.iteye.com/blog/1121157中有JMM的详细介绍)
使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。
使用volatile的目的
Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低,这是volatile的
优点),而且其使用也更容易出错(这是
缺点)。
首先考虑一个问题,为什么变量需要volatile来修饰呢?
要搞清楚这个问题,首先应该明白计算机内部都做什么了。比如做了一个i++操作,计算机内部做了三次处理:读取-修改-写入。
同样,对于一个long型数据,做了个赋值操作,在32系统下需要经过两步才能完成,先修改低32位,然后修改高32位。
假想一下,当将以上的操作放到一个多线程环境下操作时候,有可能出现的问题,是这些步骤执行了一部分,而另外一个线程就已经引用了变量值,这样就导致了读取脏数据的问题。
通过这个设想,就不难理解volatile关键字了。
另外,volatile可以用在任何变量前面,但不能用于final变量前面,因为final型的变量是禁止修改的。也不存在线程安全的问题。
volatile可以用更低的代价替代同步,那么
为什么代价更低?
同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能.
而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低。
volatile与synchronized比较?
volatile 变量可以被看作是一种“程度较轻的synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。
Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。
什么意思呢?看看下面这个例子:
比如volatile变量失效的一中情况:
http://caoruntao.iteye.com/blog/658074
声明为volatile的简单变量如果当前值由该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式
n++;不是原子操作
这同时也说明了为什么说volatile容易出错,因为volatile仅仅能保证变量可见性, 无法保证原子性。因此volatile运算有可能存在脏数据问题。
虽然增量操作(n++)看上去类似一个单独操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。实现正确的操作需要使 x 的值在操作期间保持不变,而 volatile 变量无法实现这点。(然而,如果将值调整为只从单个线程写入,那么可以忽略第一个条件。)
解决这个问题的方法:一是上文给出的synchronized同步方式,但是这显然违背了使用volatile的初衷。另一种是采用CAS非阻塞算法(打个广告在
http://hellosure.iteye.com/blog/1126541介绍ConcurrentLinkedQueue中有详细介绍,有兴趣可以看看)
正确使用volatile 的模式
很多并发性专家事实上往往引导用户远离 volatile 变量,因为使用它们要比使用锁更加容易出错。然而,如果谨慎地遵循一些良好定义的模式,就能够在很多场合内安全地使用 volatile 变量。要始终牢记使用 volatile 的限制 —— 只有在状态真正独立于程序内其他内容时才能使用 volatile —— 这条规则能够避免将这些模式扩展到不安全的用例。
具体的使用模式请参考
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html,这是篇很好的文章,建议仔细看看
分享到:
相关推荐
java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...
Java并发编程:volatile关键字解析
volatile关键字基本介绍 volatile可以看成是synchronized的一种轻量级的实现,但volatile并不能完全代替synchronized,volatile有synchronized可见性的特性,但没有synchronized原子性的特性。 可见性即用volatile...
C/C++ 嵌入式 一些关键字: volatile关键字 Const关键字 static关键字 mutable 关键字
C语言中关键字volatile的作用,使用说明和例子
一个生动的例子,详解了Volatile关键字对变量的声明在不同编译环境下可能造成不同的结果
java volatile 关键字 学习
主要讲述java线程volatile关键字
java里的volatile关键字详解
深入理解 volatile 关键字.doc
6vc中volatile关键字的应用共4页.pdf.zip
volatile是java中的关键词之一,这篇文章主要给大家介绍了关于Java中volatile关键字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
java里的volatile关键字详解.pdf
C++Volatile关键字[参考].pdf
详细描述关于votatile关键字使用,可以帮助你加深对volatile关键字的理解和使用。
多方面解读Java中的volatile关键字.rar
java语言的volatile教程,java语言的volatile关键字到底怎么用
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如 操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行 优化,从而可以提供...
volatile这个关键字,不仅仅在Java语言中有,在很多语言中都有的,而且其用法和语义也都是不尽相同的。这篇文章主要介绍了Java中的volatile关键字,需要的朋友可以参考下
本文详细解读一下volatile关键字如何保证变量在多线程之间的可见性,对Java中volatile关键字实现原理感兴趣的朋友一起通过本文学习吧