大道理不讲多了用实验说话,以下是标准C++写的一个最简单的例子来诠释volatile的作用
操作系统:Win7 64位
编程IDE:Visual Studio 2012
编译模式:release
例子原理:对于全局变量i,在主线程延迟3s赋值,在另一个线程从一开始持续打印输出这个i,看i有无改变
例子源码:
#include <iostream>
#include <thread>
int i=80;//如果前面加上关键字violatile,即violatile int i=80;可避免在Release模式BUG
//睡眠多少毫秒
void Sleep_MS(long long ms)
{
std::chrono::milliseconds timespan(ms);
std::this_thread::sleep_for(timespan);
}
void thread_proc()
{
while (true)
{
Sleep_MS(500);
printf("输出i的值:%d\r\n",i);
//std::cout << "thread id = " << std::this_thread::get_id() << std::endl;
}
}
int main(int argc, char* argv[])
{
std::thread td(thread_proc);
Sleep_MS(3000);
i=10;
while (1);
return 0;
}
上述执行结果可以发现,在release模式下多线程访问同一个变量的时候,他是不能检测到这个变量在其他线程的更改的,这是编译优化的bug,若要准确得到这个变量的正确值,那么就该在他前面加上violatile关键字。实际上violatile关键字正如他的本意“不稳定”,他让编辑器认知到这个变量是不稳定的,很容易被别的线程或则别的其他东西所改变,
比如:操作系统、硬件或者其它线程,所以必须每次从内存准确读出,形象的说就是不能读缓存什么之类.
总结:
由于编译器release下优化的bug,导致没有用violatile修饰的变量往往因为一些因素(典型的就是多进程非本进程修改过这个变量),使得程序无法正确读对这个变量,所以要用violatile来修饰这个变量,解决此bug