volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。

一个参数可以既是const又是volatile,它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

对于这样的代码:

volatile int i = 10;
int a = i;
... //其他代码,并未明确告诉编译器,对i进行过操作
int b = i;

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

一般说来,volatile用在如下的几个地方:

  1. 中断服务程序中修改的供其它程序检测的变量需要加volatile;
  2. 多任务环境下各任务间共享的标志应该加volatile;
  3. 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。

在多线程中,我们可以利用锁的机制来保护好资源临界区。在临界区的外面操作共享变量则需要volatile,在临界区的里面则non-volatile了。

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

参考文献

[1] 讲讲C++中的volatile关键字
http://www.cnblogs.com/Chase/archive/2010/07/05/1771700.html

[2] 志在千里——volatile
http://blog.csdn.net/jingxuewang110/article/details/6759044

[3] C中的volatile用法
http://www.cnblogs.com/chio/archive/2007/11/24/970632.html

volatile限定符的更多相关文章

  1. [汇编与C语言关系]5. volatile限定符

    现在研究一下编译器优化会对生成的指令产生什么影响,在此基础上介绍C语言的volatile限定符.首先看下面的C程序: /* artificial device registers */ unsigne ...

  2. 类型限定符volatile

    目录 类型限定符volatile 强制内存读取 禁止编译优化 注意:volatile不能够保证线程同步 volatile bool flag; volatile int a; 添加volatile限定 ...

  3. C语言中类型限定符

    通常用类型和存储类别来描述一个变量. C90还增加了两个属性:恒常性(constancy).易变性(volatility): 分别用关键字const和volatile来声明. 这两个关键字创建的类型是 ...

  4. C 类型限定符

    C 类型限定符 1. Introduction C 语言中的大部分类型都可以用称为限定符(qualifier)的关键字 const. volatile. restrict. _Atomic 加以限定. ...

  5. C++说明符和限定符

    有些被称为存储说明符(storage class specifier)或cv-限定符(cv-qualifier)的C++关键字提供了一些有关存储的信息.下面是存储所说明符:* auto (在C++11 ...

  6. 浅谈const限定符

    什么是const限定符? Const限定符是我们通常所说的常量限定符,被const修饰的对象具有常量性质,只能读,不能写. 为什么使用const限定符? 用const变量取代“魔数”,代码更容易理解和 ...

  7. ISO/IEC 9899:2011 条款6.7.3——类型限定符

    6.7.3 类型限定符 语法 1.type-qualifier: const restrict volatile _Atomic 约束 2.除了指针类型(其被引用的类型是一个对象类型)之外的类型,不应 ...

  8. Android使用最小宽度限定符时最小宽度的计算

    Android开发中最头疼的问题之一就是兼容不同尺寸和分辨率的设备.这里推荐一篇总结的比较完整的<Android开发:最全面.最易懂的Android屏幕适配解决方案>.这篇文章对屏幕兼容的 ...

  9. .NET LINQ 限定符操作

    限定符操作      限定符运算返回一个 Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表 ...

随机推荐

  1. Visual Studio TFS

    Overview:Active Directory环境下搭建TFS(一个domain内,with Domain Controller): 1)最简单的环境(这俩拓扑是从TFSAdmin文档中截取的,从 ...

  2. webSql的简单小例子

    初始化websql数据库的参数信息 var config = { name: 'my_plan', version: '', desc: 'manage my plans', size: 20 * 1 ...

  3. SQL server 上机练习题

    首先创建一个数据库,里面有 登录表 学生表   课程表   选课表 成绩表 1. 查询Student表中的所有记录的Sname.Ssex和Class列.2. 查询教师所有的单位即不重复的Depart列 ...

  4. Java 基础入门随笔(7) JavaSE版——面向对象定义、特征:封装、构造函数

    面向对象 面向过程:对于面向过程思想,强调的是过程(动作). 面向对象:对于面向对象思想,强调的是对象(实体). 特点: 1,面向对象就是一种常见的思想.符合人们的思考习惯.2,面向对象的出现,将复杂 ...

  5. Shell基础笔记一

    由于工作需要,开始学习Shell编程,都是一些简单的基础知识,现整理收集分享出来,希望对大家有帮助 -------------------------------------------------- ...

  6. Springboot + SLF4j + Log4j2 打印异常日志时,耗时要5-6秒

    1.使用jps -l 查看springboot项目的进程ID 2.使用命令jstack -l 进程ID > log.txt 打印堆栈信息到文件,内容如下: "http-nio-8065 ...

  7. 【转载】原 IntelliJ IDEA (idea)引入eclipse web项目

    原文地址:http://my.oschina.net/u/1170781/blog/192731 摘要 概述IntelliJ IDEA,以后都简称为idea,鼓捣了很久,看了很多例子才搞出来,希望对其 ...

  8. MongoDB 启动和关闭

    重启命令 service mongodb restart 启动命令 mongod -f /data/tools/mongodb/config/config.conf 必须要带配置文件才能启动 关闭命令 ...

  9. 出现For input string: "" 错误

    然后是因为后台生成的是一个数组,前台取的是一个对象,所以会产生这个错误 前后台交互时 mv.addObject("vo1",fhList.get(0));}将数组改成fhList. ...

  10. TestNG忽略测试

    用@Test(enabled = false) 声明需要被忽略执行的测试方法 package com.janson; import org.testng.annotations.Test; publi ...