C语言volatile的本质(三十四)
1.保证内存可见性
通俗来说就是,线程A对一个volatile变量的修改,对于其它线程来说是可见的,即线程每次获取volatile变量的值都是最新的。
当一个变量被 volatile 修饰时,任何线程对它的写操作都会立即刷新到主内存中,并且会强制让缓存了该变量的线程中的数据清空,必须从主内存重新读取最新数据。
在线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。
当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。
当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。
volatile的本质:
volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。
综上所述,频繁地使用volatile很可能会增加代码尺寸和降低性能,但它却可以保证程序的正确性,所以在合适的地方使用volatile关键字是必要的。
volatile的本意是“易变的” 因为访问寄存器要比访问内存单元快的多,从寄存器里读取,但有可能会读脏数据。
当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。
*************************************************************************************
(1)使用中断改变对象值的情况
我们在中断服务程序中操作了某个对象,比如谁改变了一个变量的值。而在其它程序中我们希望通过这个变量值得改变去进行一些操作。在这个时候,我们使用或者不使用volatile关键字,可能得到截然不同的结果。
如果我们将变量定义为:static int var=0; ,然后再中断服务成勋中将其修改为:var=1,但是在另一函数中使用它但不会修改它,那么编译器会认为它没有变化,从而直接使用寄存器中的副本。
如果我们将变量定义为:volatile int var=0;,那么结果就完全不同了,每次在函数中使用var变量时,都会重新读取,而不会使用寄存器中的副本。
(2)多任务共享标志的情况
多任务共享时,其实也是一样的,在一个任务中修改了一个对象后,在另一个对象中应用它,但编译器并没发现在该任务中对它有修改。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。从而并不能响应在另一任务下的变化。
在这种情况下,一般我们都需要使用volatile关键字来定义任务间共享的标识。
(3)硬件寄存器内存映射的情况
内存映射的情况是非常多的,比如我们将外设的寄存器映射到内存的某一段区域;再比如我们同过DMA方式将数据直接写到内存中的某一段区域。
由于我们外部的数据都是直接进入了内存区域,而程序知识引用它的值。编译器优化时可能就直接采用寄存器中的副本了。佷显然这不是我们需要的结果,这时将这段内存对应的变量声明为volatile,则可以保证我们的需求。
*************************************************************************************
相关文章
- C语言编程优化运行速度
- 【C语言入门教程】4.7 指针的地址分配 - mallocl(), free()
- 【C语言入门教程】4.6 指针 和 数组
- 【C语言】 Linux下编译提示pow未定义引用
- OC语言类的本质和分类
- C语言丨深入理解volatile关键字
- [C语言]数据类型与计算
- ZZNUOJ_用C语言编写程序实现1218:反转a+b(附完整源码)
- ZZNUOJ_用C语言编写程序实现1363:男生女生(附完整源码)
- ZZNUOJ_用C语言编写程序实现1371:无重复的排序(附完整源码)
- ZZNUOJ_用C语言编写程序实现1375:画箭(附完整源码)
- 【C语言项目设计】万年历系统
- C语言中动态内存分配的本质是什么?
- C语言结构体笔记
- C语言线性表-单链表按位置与按值增删改查(带容错)
- C语言单链表操作模板,初始化增删改查等操作
- 在C语言系统中,假设int类型数据占2个字节,则double、long、unsigned int、 char类型数据所占字节数分别多少()
- C语言之数组和指针位移的本质(四十五)
- C语言内存管理
- C语言逆向——数组和结构体,数组多维只是一个编译构造的假象,本质会转成一维数组,结构体的话最难的就是对齐了
- C语言指针是什么?1分钟彻底理解C语言指针的概念