前些日子在看些多线程方面的资料,当我看到对volatile这个关键字的解释的时候,让我出现了一些困惑!
在某些书籍中说
写道
'在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步.当你定义long或double变量时,如果使用volatile关键字,就会获得(简单的赋值与返回操作的
)原子性'
然而一篇IBM技术论坛上的文章似乎又有不同的观点(http://www.ibm.com/developerworks/cn/java/j-jtp06197.html)
Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。
两段文字粗略一看,似乎搞得人晕头转向了,更加难以理解volatile的特性了!
但是请注意第一段文字中被标红的一段"简单的赋值与返回操作的
原子性",这里似乎说明这种原子性不可靠!因为long和double类型的长度都是64位的,由于jvm的原因可能造成撕扯现象.这里的简单原子性应该是保证变量不会被撕扯得面目全非吧!
有人对Volatile做如下整理(http://hi.baidu.com/lifa868/blog/item/22bc7718926ad772dbb4bd0e.html):
写道
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。
而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。
使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。
由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。
后来在一篇对C#中volatile相关文章中看到这样一句话(http://www.cnblogs.com/lucifer1982/archive/2008/03/23/1116981.html):
写道
到这里,我们已经知道volatile提供的同步机制还不足以能够实现线程安全计数器。因为计数器虽然简单,却是三种操作的组合,如果多线程试图进行增量操作,很可能会丢失其更新值。
还有这样一种理解,volatile在增量操作时已经失去了原子性,如i++其实是i=i+1,这种情况下我们就认为原子性将丢失。而在i=m的情况下是可以保证原子性的!
这样一来是不是可以做出以下理解:
java中有主内存和工作内存之分,当变量变申明volatile之后.
1.所有的读写操作都直接从主内存进行.
2.每次对变量的修改强行回写到主内存中,供其他线程共享!
最后想做一个假设,以说明自己对上诉观点的理解:
static volatile int i=0;
static void add(){
i++;
}
.......
在多线程并发访问add()方法的时候,T1线程和T2线程同时进入add(),由于{i++}=={i=i+1}其实是先从主内存中读取i,而后对i进行增量修改,最后回写主内存。那就有可能出现这样的情况:在T1进入后读取的i=9,T2同时也读取的也是9,T1线程操作后i=10然后回写主内存,T2也同时完成操作i=10也回写主内存,那T2的回写值是不是就覆盖了T1的回写值,这也就是上述中所提及的“如果多线程试图进行增量操作,很可能丢失其更新值”。
由于对jvm内存设计不是非常熟悉,不清楚实际jvm中对volatile是否在内存也是这样操作的,希望大家能提供更多资料以便相互交流,探讨!
分享到:
相关推荐
java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...
这一点我们在第 15 节课和第 16 节课 已经分析过了。为了解决这个问题,Java 语言在规范中做出了明确的规定,也就是在 JSR 133 文档中规定了 Ja
主要讲述java线程volatile关键字
java volatile 关键字 学习
1. 什么是线程? 2. 线程和进程有什么区别? 3. 如何在 Java 中实现线程? 4. 用 Runnable 还是 Thread? 5. Thread 类中的 start () 和 run () 方法有什么...9. Java 中的 volatile 变量是什么? ......... ........
【Java面试题】volatile的作用
从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性
Java并发编程:volatile关键字解析
java语言的volatile教程,java语言的volatile关键字到底怎么用
violate java_Java 之 volatile 超级详解
Java并发编程系列- volatile;Java并发编程系列- volatile;Java并发编程系列- volatile;Java并发编程系列- volatile;Java并发编程系列- volatile;
主要介绍了Java Volatile 变量详解及使用方法的相关资料,需要的朋友可以参考下
主要介绍了java volatile关键字使用方法及注意事项的相关资料,当一个变量被声明为 volatile 后,java 内存模型确保所有使用该变量的线程能看到相同的、一致的值。,需要的朋友可以参考下
volatile是java中的关键词之一,这篇文章主要给大家介绍了关于Java中volatile关键字的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
在本文里我们给大家分享的是关于java volatile关键字作用及使用场景的相关知识点内容,需要的朋友们学习下。
synchronized是阻塞式同步,在线程...这个实际对普通变量没有规定的,而针对volatile修饰的变量给Java虚拟机特殊的约定,线程对volatile变量的修改会立刻被其他线程所感知,即不会出现数据脏读,从而保证数据的可见性。
java里的volatile关键字详解