volatile关键字
volatile关键字总结
背景
volatile
介绍
volatile
关键字告诉编译器,不要去寄存器中访问某个变量,而是直接去内存中读取。
volatile
关键字的使用场景
volatile
常用的场景:
- 并行设备的寄存器,如状态寄存器
- 多线程程序
- 一个中断服务子程序访问到的非自动变量
总结
为什么在中断中修改了i的值,而在main函数中的i没有被编译器认为是1。而如果不是通过中断修改i,而只是在程序中修改i的值,main函数中的i就会被认为是1。
这就类似于:就比如我在盯着一个房间有没有人,我一开始进这个房间看了一眼,没有人,那么这个时候我就只需要在门口盯着,确保没有人从门口进去就行了。这个时候中断来了,就类似时间被暂停了,然后有个人进房间了。然后时间恢复,这个时候我依旧只会盯着门看,不会进门去看一下,确认房间是否有人。因为我认为我一直在盯着门。
这个就类似一开始编译器从内存中拿出i的值放到寄存器中,然后if(i)反复判断。编译器就会认为我中间没有去做其他事,没有必要再去从内存中拿一次i的值。
而如果再程序中修改i的值,就类似我在看着门,突然有事离开。然后再回来,我要确保我出去的这段时间,有没有人进房间,所以会进房间看一次有没有人。就类似从内存中取一次i的值。
1 |
|
上述程序的本意是希望ISR_2中断产生时,在main函数中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。
1 |
|
没有使用volatile
关键字,则该代码会被优化为:
1 |
|
所以我们需要使用volatile
关键字,来告诉编译器不要优化。
小练习
下面函数有什么问题?
1 |
|
上面有可能a会被其他的线程所改变。更正:
1 |
|
总结
通过上面的代码,volatile
关键字似乎不仅仅是阻止,编译器优化关于寄存器分配的优化。由第二段代码可知,volatile
还可以阻止编译器进行死代码消除的优化。是否可以认为,只要添加了该关键字,就可以认为编译器不会随便对该对象进行优化。