和const对应,const表示变量是恒定不变的,而Volatile则相反,表示变量随时均可能被改变,所以每次获取变量都须要从新到内存中获取;多线程
有这样的代码:优化
int i = 10;spa
int a = i;线程
...debug
int b = i;进程
printf("a=%d,b=%d", a, b);内存
在debug模式下,代码没有被优化过,咱们能获得a=10,b=10这样的结果,可是在Release模式下,会执行代码优化,编译器执行到int i = 10时会将i存入寄存器中,当执行到int b = i这一行时,发现i从int i = 10以后都没有被改变过,所以会将保存到寄存器中的i直接赋值给b,假定在此期间某个外部因素改变了i的值,编译器是不知道的,所以这个时候的i和寄存器中的i数值是不同的,寄存器中的i并非最新的内存数据。编译器
bool bChanged = false;string
void thread1()编译
{
while(!bChanged){...};
}
void thread2()
{
bChanged = true;
}
运行线程2后线程1是不会中止的,缘由就在于线程1已经将bChanged从内存读取到CPU寄存器中,bChanged的内存改变线程1是没法知道的,要让代码能正确执行,除非关闭Release模式下的代码优化功能。
程序和其余进程或系统进程经过共享内存访问数据时,其余进程能够随时改变内存中的数据,此时不管你执行多少次int a = i,int b = i; int c = i;可能都没法获得最新的i值,仍是由于寄存器拷贝的问题;一样还有访问端口数据,其实和访问内存数据同样。好比硬件将参数映射到内存的某个区域,程序经过一个struct来读取参数结构:
struct myparam {
int x;
int y;
long size;
long size;
char[32] name;
}PMYPARM;
PMYPARM yParam = (PMYPARM)memory_addr;
此时yParam指向的是一段真实的,且不容改变地址的内存地址,然而系统的其余进程在不断的刷新这段内存区域(内存区域是能够被多核CPU同时访问的,只要获取到总线控制权便可),所以每次取回的数据均可能不同。
定义这个关键字就是要告诉编译器,每次取得该变量的值,都须要到内存中获取:
volatile int i = 10;
int a = i;从新到内存中取得i的数据赋值给a;
int b = i;从新到内存中取得最新的数据赋值给b;
int c = i;从新到内存中获取i的最新数据。
上面的结构体能够这样定义:
volatile PMYPARM yParam = (PMYPARM)memory_addr;
定义一个可变的结构体,每次访问其成员时都须要从新从内存获取最新的数据:
int x = yParam.x;
long size = yParam.size;
string name(yParam.name);