`
wezly
  • 浏览: 471760 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

关于volatile变量的理解

阅读更多

前些日子在看些多线程方面的资料,当我看到对volatile这个关键字的解释的时候,让我出现了一些困惑!

 

在某些书籍中说

写道
'在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步.当你定义long或double变量时,如果使用volatile关键字,就会获得(简单的赋值与返回操作的 )原子性'
 

 然而一篇IBM技术论坛上的文章似乎又有不同的观点(http://www.ibm.com/developerworks/cn/java/j-jtp06197.html)

Java代码 复制代码
  1. volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。  
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.每次对变量的修改强行回写到主内存中,供其他线程共享!

最后想做一个假设,以说明自己对上诉观点的理解:

Java代码 复制代码
  1. static volatile int i=0;   
  2. static void add(){   
  3.     i++;   
  4. }   
  5. .......  
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是否在内存也是这样操作的,希望大家能提供更多资料以便相互交流,探讨!

分享到:
评论

相关推荐

    从汇编角度理解volatile

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

    深入理解Java内存模型??volatile

    理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这些单个读/写操作做了同步。下面我们通过具体的示例来说明,请看下面的示例代码: class VolatileFeaturesExample { ...

    #define((volatile unsigned *) ) 讲解

    本文介绍了是用C语言的一个关于volatile的问题。

    pc-lint 经验(中文)

    3.8 volatile变量检查 4 PC-Lint软件使用方法 4.1 安装与配置 4.2 PC-Lint与常用开发工具的集成(Visual C++,Source Insight,UEdit) 5 总结 参考文献 附录一 PC-Lint 重要文件说明 附录二 错误信息禁止选项说明 ...

    嵌入式软件研发面试题目

    #include<setjmp.h>static jmp_buf buf;main() { volatile int b; b =3; if(setjmp(buf)!...volatile 不会被编译器优化影响,在longjump 后,它的值 是后面假定的变量值,b最后的值是5,所以5被打印出来.

    Java多线程并发编程 Volatile关键字

    volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解...只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile 理解成变量的锁

    单片机与DSP中的ADS下C语言中局部变量的存储位置分配

    而实际情况,有些出入录,肯能更容易理解。  这一段代码,唯一的用途,就是分配变量。int func1(void) { volatile int father; volatile int mother; volatile int boy; volatile int girl; father = ...

    深入理解嵌入式开发之系统开发篇全覆盖

    Tp05.volatile Tp06.位操作 Tp07.中断处理程序: Tp08.字长问题 Tp09.void的作用 Tp10.数组与普通指针的转化 TP11.宏的使用及副作用 TP12.指针的类型 TP13.一个结构体可以包含指向自己的指针吗? TP14....

    深入理解Java内存模型

    Agenda: •什么是Java内存模型JMM •内存可见性 •有序性 •指令重排序 •内存屏障 •顺序一致性与Happens-before规则 •volatile, synchronized, 原子变量,锁, final的原理

    C语言进阶-牟海军.pdf

     堆和栈、全局变量和局部变量、生存期和作用域、内部函数和外部函数、指针变量、指针数组和数组指针、指针函数和函数指针、传址和传值、递归和嵌套、结构体和共用体、枚举、位域等较难理解的核心概念的阐述和对比...

    C语言进阶 作者 Wrestle.Wu

     堆和栈、全局变量和局部变量、生存期和作用域、内部函数和外部函数、指针变量、指针数组和数组指针、指针函数和函数指针、传址和传值、递归和嵌套、结构体和共用体、枚举、位域等较难理解的核心概念的阐述和对比...

    Java 多线程编程面试集锦20道问题解答Java多线程编程高难度面试题及解析

    此外,还探讨了线程间通信、线程优先级、守护线程、线程组、可重入锁、线程局部变量等关键概念和技术。 每个问题都附带了精确而深入的答案解析,涵盖了多线程编程的各个方面。您将了解线程安全的实现、死锁的避免...

    Netty中注册Channel.xlsx

    从示意图中,体会Netty的异步编程和事件驱动。以及深入理解volatile关键字,以及多个线程访问共享变量

    深入理解JVM内存结构及运行原理全套视频加资料.txt

    2019最新深入理解JVM内存结构及运行原理(JVM调优)高级核心课程视频教程下载。JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java... 第109讲 volatile的内存语义 00:12:04  第110讲 final域内存语义

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    要了解面向对象编程(OOP)的基本概念,需要理解 OOP 的三个主要概念,它们撑起 了整个 OOP 的框架。这三个概念是:封装、继承性和多态性。除此以外,还需了解对象、 类、消息、接口、及抽象等概念。 2.2.1 ...

    嵌入式系统/ARM技术中的在嵌入式软件编程中深入理解关键字

    C语言以其简洁、高效和强大等特性成为嵌入式软件编程的首选语言,但是某些关键字,例如const、static、extern和volatile等,在不同的场合具有不同的含义,而且某些用法晦涩难懂,为此本文详细介绍这些关键字的用法...

    涵盖了90%以上的面试题

    介绍一下volatile jdk1.5新特性 jdk1.7新特性 jdk1.8新特性 java语言有哪些优点? 同一个.java文件中是否可以有多个main方法 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 如何在main方法执行...

Global site tag (gtag.js) - Google Analytics