【C++】Volatile关键字浅析

一、概念

   volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统,硬件或者其他线程等。
   遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:volatile int vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

volatile int i=10;  
int a = i;  
...  
// 其他代码,并未明确告诉编译器,对 i 进行过操作  
int b = i;  
volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;

   volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。
   而优化做法是,由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。

二、特性

  • 易变性
volatile int *p = /* ... */;
int a, b;
a = *p;
b = *p;

不使用volatile时,b会直接使用a=p后存在于寄存器中的p值,使用volatile时,每次都会从内存中重新读取

  • 不可优化
int a, b, c;
a = 1, b = 2, c = 3;
cout << a << b << c;

变量a,b,c没有被volatile修饰时,会被优化成三个常量,使用volatile后不可优化,需要将三个变量从内存读入寄存器中,再进行输出

  • 顺序性
volatile int something = 0;
volatile int flag = false;


Thread1()
{
    
    
	something = 1;
	flag = true;
}


Thread2()
{
    
    
	if (flag == true)
	{
    
    
		assert(something == 1);


		other things;
	}
}

上面的代码看似能够保证something = 1和flag = true的执行顺序,也能确保Thread2在flag == true时,即Thread1执行完something = 1后,再执行other things。但由于编译后的代码最终通过CPU来执行,CPU为了提高代码运行的效率,也会对代码的执行顺序进行调整。
可见三volatile解决的问题

猜你喜欢

转载自blog.csdn.net/Vcrossover/article/details/113696771