前些日子在看些多线程方面的资料,当我看到对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 ...
例如,如果你尝试通过`volatile`变量实现一个计数器,像这样: ```java volatile int counter = 0; public void increment() { counter++; } ``` 上述代码中的`counter++`操作并不是原子的,它实际上包含了读取、...
Java 线程 volatile 关键字详解 Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。volatile 变量的同步性较差,但它有时更简单并且开销更低。volatile 变量可以被看作是一种 “程度较轻的 ...
java volatile 关键字 学习
【Java面试题】volatile的作用
- 原子性:虽然读写操作是原子性的,但`volatile`不能保证复合操作的原子性,例如`i++`这样的操作就不是原子的,因为这涉及到读、加、写三个步骤。 - 互斥性:`volatile`并不能替代`synchronized`来实现线程间的互斥...
从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性
### Java并发编程:volatile关键字解析 #### 一、内存模型的相关概念 在深入了解`volatile`关键字之前,我们首先需要理解计算机内存模型的一些基本概念。在现代计算机系统中,CPU为了提高执行效率,会将频繁访问的...
volatile
java语言的volatile教程,java语言的volatile关键字到底怎么用
`这样的单次赋值操作,`volatile`可以保证其原子性,但对于`flag++`这样的复合操作,由于可能存在读、修改、写三个步骤,`volatile`无法确保这些操作的原子性,可能导致线程安全问题。 4. 使用场景: `volatile`...
JavaMain方法是Java程序执行的入口点,理解其工作原理对于任何Java开发者来说都是至关重要的。在Java中,每一个可独立运行的程序都需要一个包含`main`方法的类。这个`main`方法定义了程序的起点,Java虚拟机(JVM)...
"Java中的Volatile关键字详解" Java中的Volatile关键字详解是Java中的一种关键字,用于保证线程之间的可见性、原子性和有序性。下面是对Java中的Volatile关键字详解的知识点总结: 一、基本概念 1. 可见性:可见...
Java中的`volatile`关键字是用来修饰变量的,它主要用于解决多线程环境下的数据同步问题。在Java语言中,`volatile`变量提供了一种轻量级的同步机制,它确保了共享变量的可见性和有序性,但并不保证原子性。 **可见...
Java并发编程中的`volatile`关键字是一个非常重要的概念,它用于解决多线程环境下的数据同步问题。`volatile`关键字提供了两种关键特性: 1. **保证可见性**:当一个线程修改了`volatile`变量,这个修改对于其他...
Java基础:volatile详解 Java基础:volatile详解问:谈谈你对volatile的理解? volatile是Java虚拟机提供的轻量级的同步机制,它有三个特性:保证可见性、不保证原子性、禁止指令重排。 1、volatile保证可见性 ...
volatile关键字在Java编程语言中扮演着重要的角色,特别是在多线程环境下的同步和可见性问题。它是Java内存模型(JMM)的一部分,用于确保共享变量的可见性和有序性,但不保证原子性。 1. **volatile的可见性**:当...