一般对于volatile的解释是这样的:将变量定义为volatile可以防止编译器对变量进行优化,每次均从内存中访问变量,而不是寄存器。既然让编译器优化可以提高访问速度,那为什么又要不用它以及什么时候不用它?其实主要是配合的问题,一个变量可能在寄存器中,也可能在内存中,如果程序只有一个执行流且没有跳转,那么变量不管放到内存还是寄存器,理论上在编译阶段编译器是能够知道变量的具体位置的,使用时就不会出现问题。事实上编译器是通过一个简单的规则来保证的:局部变量一般会放到寄存器中,全局变量在函数开始时必然是操作内存,之后可能是放入寄存器,到函数结束时必然将全局变量的值再写入内存(如果有写的话),这样每次函数调用时全局变量的最新值都在内存中,且都从内存中访问,保证了数据的一致性。但这种一致性在多执行流或有跳转的情况下就有问题了 《从汇编角度理解volatile》 volatile关键字在编程中扮演着重要的角色,它主要用于多线程编程和与硬件交互的场景。通常的理解是,volatile告诉编译器不要对某个变量进行优化,每次读取该变量时都直接从内存中获取,而不是使用寄存器中的副本。这样做是为了确保在多线程环境下或者有外部因素(如硬件设备)影响变量时,能正确地反映变量的最新状态。 我们来看一下在单线程、无跳转的情况。在这种情况下,编译器可以通过简单的规则来管理变量的位置:局部变量通常存储在寄存器中,全局变量在函数开始时会直接操作内存,然后可能被放入寄存器。当函数结束时,全局变量的值会被写回内存,以保证每次函数调用时全局变量的值都是最新的。然而,这种保证在多线程或多执行流的场景下就不再有效。 在多线程环境中,线程间共享的变量通常需要加锁来保证数据一致性。例如,我们有一段使用互斥锁的C代码(mutex.c)。在这个例子中,`g_i`是全局变量,两个线程分别对其进行修改。即使不使用volatile,由于每次访问全局变量`g_i`时都通过互斥锁来控制,编译器在访问全局变量时都会从内存中读取,因此加不加volatile并不会改变最终的结果。 但是,如果线程间共享变量没有加锁,情况就会有所不同。比如在Nomutex.c的示例中,一个线程在死循环中不断修改全局变量`g_i`,编译器可能会优化掉这些重复的操作,因为它认为这些操作在死循环中没有实际效果。然而,这将导致其他线程无法观察到`g_i`的变化,除非使用volatile关键字来阻止编译器的优化。 除了多线程环境,volatile在设备驱动编程中也非常重要。设备寄存器的读写操作需要volatile来确保每次都能直接从硬件读取或写入,因为设备的状态可能会在程序运行时被硬件实时更新。此外,像setjmp/longjmp、goto等跳转语句以及信号处理等非线性控制流也会使编译器无法准确预测变量的访问路径,这时也需要volatile来确保变量的正确读取。 总结来说,volatile的作用是强制编译器每次从内存中读取或写入变量,以应对多线程环境、硬件交互或其他不可预知的外部影响。在多线程共享变量并使用互斥锁保护时,加不加volatile可能不会有实质区别,因为互斥锁已经保证了对内存的访问顺序。但在没有同步机制的多线程环境中,或者涉及到硬件设备、非线性控制流时,volatile是不可或缺的,以避免编译器的优化导致数据不一致。
剩余26页未读,继续阅读
- 羽毛小子2012-07-17讲的挺详细的,没看懂啥意思
- aishadow132014-06-18没看懂啥意思
- 粉丝: 0
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于Vue和SpringBoot的企业员工管理系统2.0版本设计源码
- 【C++初级程序设计·配套源码】第2期-基本数据类型
- 基于Java和Vue的kopsoftKANBAN车间电子看板设计源码
- 影驰战将PS3111 东芝芯片TT18G23AIN开卡成功分享,图片里面画线的选项很重要
- 【C++初级程序设计·配套源码】第1期-语法基础
- 基于JavaScript、CSS、HTML的简易DOM版飞机游戏设计源码
- 基于Java开发的日程管理FlexTime应用设计源码
- SM2258XT-BGA144-4BGA180-6L-R1019 三星KLUCG4J1CB B0B1颗粒开盘工具 , EC, 3A, 94, 43, A4, CA 七彩虹SL300这个固件有用
- GJB 5236-2004 军用软件质量度量
- 30天开发操作系统 第 8 天 - 鼠标控制与切换32模式