首页 > 代码库 > volatile 的用法

volatile 的用法

volatile :用于防止相关变量被优化。

volatile int i=10;
int j = i;
int k = i;

 

(1)volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。

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

 

常用情况:

1.例如对外部寄存器的读写。对有些外部设备的寄存器来说,读写操作可能都会引发一定硬件操作,但是如果不加volatile,编译器会把这些寄存器作为普通的变量处理,例如连续多次的对同一地址写入数据时,会被优化为只有最后一次的写入。

2.中断使用时。如果一个全局变量,在中断函数和普通函数里都用到。那最好对这个变量加volatile修饰,否则普通函数里,可能会仅从寄存器里读取这个变量以便加快速度,而不去实际地址读取该变量。

----附加其工作原理:理论上来讲每次使用a的时候都应该从a的地址来读取变量值,但是这存在一个效率问题,就是每次使用a都要去内存中取变量值,然后再通过系统总线传到CPU处理,这样开销会很大。所以那些编译器优化者故作聪明,把a读进CPU的cache里,像上面的代码,假如a在赋值期间没有被改变,就直接从CPU的cache里取a的副本来进行赋值。但是bug也显而易见,当a在赋给b之后,可能a已经被另一个线程改变而重新写回了内存,但这个线程并不知道,依旧按照原来的计划从CPU的cache里读a的副本进来赋值给c,结果不幸发生了。

于是,volatile作为正义的化身就出现了!当变量加上了Volatile时,编译器就老老实实的每次都从内存中读取这个变量值,否则就还按照优化的方案从cache里读。

3.多任务环境下个任务间共享的标志应该用volatile。

 

volatile 的用法