volatile

简介: 当一个对象的值可能会在编译器的控制或监测之外被改变时,例如一个被系统时钟更新的变量,那么该对象应该声明成volatile。因此编译器执行的某些例行优化行为不能应用在已指定为volatile的对象上。

   当一个对象的值可能会在编译器的控制或监测之外被改变时,例如一个被系统时钟更新的变量,那么该对象应该声明成volatile。因此编译器执行的某些例行优化行为不能应用在已指定为volatile的对象上。
 

   volatile修饰符的主要目的是提示编译器该对象的值可能在编译器未监测到的情况下被改变,因此编译器不能武断地对引用这些对象的代码做优化处理。

    一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
    下面是volatile变量的几个例子:
  • 并行设备的硬件寄存器(如状态寄存器)
  • 一个中断服务子程序中会访问到的非自动变量
  • 多线程应用中被几个任务共享的变量

 

 

 

 

 

以下为从网上找的参考资料:

 

volatile的用法

避免编译器优化的用法 转自<海涛的笔记>   _lindwen
  
  
  volatile的本意是“易变的”
  
  由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
  
  static int i=0;
  
  int main(void)
  {
  ...
  while (1)
  {
  if (i) dosomething();
  }
  }
  
  /* Interrupt service routine. */
  void ISR_2(void)
  {
  i=1;
  }
  
  程序的本意是希望ISR_2中断产生时,在main当中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此
  可能只执行一次对从i到某寄存器的读***作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被
  调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写***作都不会被优化(肯定执行)。此例中i也应该如此说明。
  
  一般说来,volatile用在如下的几个地方:
  
  1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
  
  2、多任务环境下各任务间共享的标志应该加volatile;
  
  3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
  
  另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实
  现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
  
  
  
  volatile 的含义
   volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并, 常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,volatile的字面含义 是易变的,它有下面的作用:
  
  1 不会在两个***作之间把volatile变量缓存在寄存器中。在多任务、中断、甚至setjmp环境下,变量可能被其他的程序改变,编译器 自己无法知道,volatile就是告诉编译器这种情况。
  
  2 不做常量合并、常量传播等优化,所以像下面的代码:
  volatile int i = 1;
  if (i > 0) ...
  
  if的条件不会当作无条件真。
  
  3 对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值***作,然而对Memory Mapped IO的处理是不能这样优化的。
  
  前面有人说volatile可以保证对内存***作的原子性,这种说法不大准确,其一,x86需要LOCK前缀才能在SMP下保证原子性,其二,RISC根本不能对内存直接运算,要保证原子性得用别的方法,如atomic_inc。
  
  对于jiffies,它已经声明为volatile变量,我认为直接用jiffies++就可以了,没必要用那种复杂的形式,因为那样也不能保证原子性。
  
  你可能不知道在Pentium及后续CPU中,下面两组指令
  
  inc jiffies
  ;;
  mov jiffies, %eax
  inc %eax
  mov %eax, jiffies
  
  作用相同,但一条指令反而不如三条指令快。   

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

相关文章
|
数据安全/隐私保护 计算机视觉
2024年2月国内如何快速注册OnlyFans最新小白教学
onlyfans软件是一个创立于2016年的订阅式社交媒体平台,创作者可以在自己的账号发布原创的照片或视频,并需要注意的是,网络上可能存在非法或不道德的应用将其设置成付费模式,若用户想查看则需要每月交费订阅。程序,建议你在使用互联网时保持警惕,并遵循相关法律法规。(现在p站没了,大家晚上懂得都懂啊)
2024年2月国内如何快速注册OnlyFans最新小白教学
|
安全 程序员 Linux
删库跑路?掌握rm命令的技巧,高效删除文件和目录!
删库跑路?掌握rm命令的技巧,高效删除文件和目录!
1124 0
|
索引
9.MySQL索引的操作(三)
9.MySQL索引的操作(三)
133 0
9.MySQL索引的操作(三)
|
SQL JSON Java
Flink数据问题之checkpoint数据删除失败如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
|
消息中间件 中间件
十年中间件最佳实践集锦,八月福利大放送
轻松应对业务增长,阿里云为在线教育“定制”丰富的中间件,助力提升系统稳定性、灵活性和反脆弱性,通过消息队列,让你的业务沟通无畅,信息不丢失,还有全年优惠大放送!
1867 39
十年中间件最佳实践集锦,八月福利大放送
|
JavaScript 前端开发
用Node.js实现一个本地的石头剪刀布游戏
前一段日子学了个石头剪刀布游戏,自己在本地进行了实现,想挂在自己服务器上让他形成一个外网可访问的游戏的时候,出了问题,是接口请求路径不对的问题,现在还不知道什么原因,等解决之后我还会更一下。
|
机器学习/深度学习 Java 开发者
LinkedList 子类|学习笔记
快速学习 LinkedList 子类
144 0
LinkedList 子类|学习笔记
|
BI 数据处理 数据安全/隐私保护
RPA教程丨银行RPA在银行业中的9大应用场景
文 | 鄂攀 根据以往项目经验,总结了银行RPA在银行业中的9大应用场景,以供参考。 第一种:银行同业对账 流程图如下: 因为涉及各银行的网银登录,所以自动化中密码储存安全性至关重要,同时还得能识别银行的安全密码登录,有的银行弹出框之后是无法进行界面元素识别的,有的即使识别也必须需要软键盘进行输入。
2585 0
|
前端开发 数据安全/隐私保护 JavaScript
Intellij Idea/Webstorm/Phpstorm 的高效快捷键
1. shift + F6可以理解为F2的豪华重量版,不但可以重命名文件名,而且可以命名函数名,函数名可以搜索引用的文件,还可以重命名局部变量。还可以重命名标签名。在sublime text中有个类似的快捷键:ctrl+shift+d。
2858 0
|
Shell
vi常用快捷键
进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后一行首 vi +/pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处 vi -r filename :在上次正用vi编辑时发生系统崩溃
1367 0