哎.要学的东西太多,时间太少.一周的工作下来要总结的东西太多,还处理不完,越积越多.大周末的好想出去玩啊.... 得嘞,废话止于此.

无聊时候乱看网页发现了volatile的一篇文章,以前曾经对volatile困惑过..所以在学习一遍http://blog.sina.com.cn/s/blog_559f6ffc01000aip.html

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
例如:
>>>>当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。也不会从寄存器重新读取而是从内存中重新读取
例如:
volatile int i=10;
int a = i; ----->//从内存中读取
...//其他代码,并未明确告诉编译器,对i进行过操作
...//其他代码,并未明确告诉编译器,对i进行过操作
int b = i;------->并不会从寄存器中读取i的值而是又一次从内存中读取i的值

>>>>volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问

volatile对应的变量可能在你的程序本身不知道的情况下发生改变
比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量
你自己的程序,是无法判定何时这个变量会发生变化
还比如,他和一个外部设备的某个状态对应,当外部设备发生操作的时候,通过驱动程序和中断事件,系统改变了这个变量的数值,而你的程序并不知道。
对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,而不会利用cache当中的原有数值,以适应它的未知何时会发生的变化。

典型的例子
for ( int i=0; i<100000; i++);
这个语句用来测试空循环的速度的
但是编译器肯定要把它优化掉,根本就不执行
如果你写成 
for ( volatile int i=0; i<100000; i++);
它就会执行了 

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
    1). 并行设备的硬件寄存器(如:状态寄存器)
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    3). 多线程应用中被几个任务共享的变量
    
    假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
    1). 一个参数既可以是const还可以是volatile吗?解释为什么。
    2). 一个指针可以是volatile 吗?解释为什么。
    3). 下面的函数有什么错误:
         int square(volatile int *ptr)
         {
              return *ptr * *ptr;
         }
    下面是答案:
    1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
    2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
    3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
    int square(volatile int *ptr) 
    {
         int a,b;
         a = *ptr;
         b = *ptr;
         return a * b;
     }
    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
     long square(volatile int *ptr) 
     {
            int a;
            a = *ptr;
            return a * a;
     }

总结就是,对于共享变量而言,这个变量有可能改变了,但这种改变并不是你所关注的程序(代码)造成的.这种情况下编译器可能会认为这个共享变量没有改变而直接使用改变前的值.而我们加上vialoate后就是在告诉编译器,不要直接用上次的值,给我从内存里面重新读取!!

对于volatile的理解的更多相关文章

  1. Java线程工作内存与主内存变量交换过程及volatile关键字理解

    Java线程工作内存与主内存变量交换过程及volatile关键字理解 1. Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行.此处的所谓内存模 ...

  2. volatile变量理解 via《Java并发编程实战》

    第3章:对象的共享 volatile关键字的理解 volatile变量,用来确保将变量的更行操作通知到其他线程.当变量申明为volatile类型后,编译器与运行时都会注意带这个变量时共享的,因此不会将 ...

  3. 对volatile的理解--从JMM以及单例模式剖析

    请谈谈你对volatile的理解 1.volitale是Java虚拟机提供的一种轻量级的同步机制 三大特性1.1保证可见性 1.2不保证原子性 1.3禁止指令重排 首先保证可见性 1.1 可见性 概念 ...

  4. volatile的理解

    用法解释 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其 ...

  5. volatile的理解和使用

    package thread; /** * Created by Administrator on 2017/1/15. */ public class Counter { public volati ...

  6. 关于java多线程关键字volatile的理解

    volatile关键字的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值. 使用volition关键字增加了实例变量在多个线程间的可见性.但volition有个致命的缺点就是不 ...

  7. (转)volatile 的理解

    对于(volatile unsigned char *)0x20我们再分析一下,它是由两部分组成: 1) (unsigned char *)0x20,0x20只是个值,前面加(unsigned cha ...

  8. Volatile关键字理解

    Volatile定义 为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量.Java语言提供了volatile,在某些情况下比锁更加方便.如果一个字段被声明成volatile, ...

  9. java中关于volatile的理解疑问?

    作者:xyzZ链接:https://www.zhihu.com/question/49656589/answer/117826278来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

随机推荐

  1. Unity3D延迟回调的封装

    最近,整理项目框架逻辑时,无意中翻到n年前封装的延迟回调管理器,就拎出来说道说道: 先说一下系统提供的几种常用的延迟回调方式: 1)Invoke(Invoke.CancelInvoke):首先需要继承 ...

  2. boost库在工作(37)网络UDP服务端之七

    前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...

  3. HDU1711-----Number Sequence-----裸的KMP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目意思: 找出b在a中的起始位置,没有则是-1 解题思路: 裸的KMP,不多说 不会KMP的话 ...

  4. android80 HttpClient框架提交数据 get方式

    package com.itheima.httpclient; import java.io.IOException; import java.io.InputStream; import java. ...

  5. LINUX 文件系统JBD ----深入理解Fsync

    http://www.cnblogs.com/hustcat/p/3283955.html http://www.cnblogs.com/zengkefu/p/5639200.html http:// ...

  6. cocos2d-x Lua与OC互相调用

    1. Lua 调用OC 先看例子: hello.lua: -- 点击回调函数 local function notifymenuCallbackTest() local luaoc = require ...

  7. oracle数据快速删除

    上文说了创建数据还原点的事,数据恢复的前提是我们在删除的时候使用了delete命令来删除,delete在删除的过程中会写日志(所以我们的数据才能够恢复),当然,写日志会导致删除速度变慢.如果我们使用t ...

  8. java 内部类学习

    类和内部类的关系就如同人和心脏的关系. 实例1:内部类的基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 //外部 ...

  9. 黑马程序员-File类+递归的简单应用

    Java File类   Java.io.File Java文件类以抽象的方式代表文件名和目录路径名.该类主要用于文件和目录的创建.文件的查找和文件的删除等. File对象代表磁盘中实际存在的文件和目 ...

  10. linux启动黑屏或无法进入会话管理器

    原因是因为更新软件时删除了/etc中的xserver配置文件,进入livecd将相关文件拷贝即可