一般对于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币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于Arduino和Python的实时歌曲信息液晶显示屏展示系统.zip
- (源码)基于C++和C混合模式的操作系统开发项目.zip
- (源码)基于Arduino的全球天气监控系统.zip
- OpenCVForUnity2.6.0.unitypackage
- (源码)基于SimPy和贝叶斯优化的流程仿真系统.zip
- (源码)基于Java Web的个人信息管理系统.zip
- (源码)基于C++和OTL4的PostgreSQL数据库连接系统.zip
- (源码)基于ESP32和AWS IoT Core的室内温湿度监测系统.zip
- (源码)基于Arduino的I2C协议交通灯模拟系统.zip
- coco.names 文件