C/C++ 中的 volatile
关键字和 const
对应,用来修饰变量,通常用于建立语言级别的 memory barrier。这是 BS 在 "The C++ Programming Language" 对 volatile 修饰词的说明:
A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.
volatile
关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。volatile
提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile
关键字,则编译器可能优化读取和存储,就极有可能暂时使用寄存器中的值,此时这个变量由别的线程更新了的话,将出现不一致的现象int volatile vInt
; 当要求使用volatile
声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。例如:const volatile int i=0;
const volatile int i=0;
这是一个有趣的语句:
const
修改i
,其被定义为一个常量,不能更改,只能初始化( “const”含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。)volatile
也修饰了i
,告诉编译器变量极有可能被未知因素更改,每次访问读值都有去内存取值( “volatile”的含义是“请不要做没谱的优化,这个值可能变掉的”,而并非“你可以修改这个值”。)这两个使用并不矛盾,所以这里的i的属性是在本程序中,i应该是只读的,不应该被修改的,但是它也可能被外部的例如中断,共享的线程通过某种方式修改(如其他线程直接调用汇编去修改),所以这里也不该被编译器优化,虽然它是只读的不该被修改的,但是它还是会改变,我们在本程序中使用的时候,还是要每次都去读它的值,这是一种“双重保险”。
因此,const
和volatile
放在一起的意义在于:
和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念:
const
或 volatile
的:const char* cpch;
volatile char* vpch;
指针自身的值——一个代表地址的整数变量,是 const
或 volatile
的:
char* const pchc;
char* volatile pchv;
volatile
修饰,但也不能保证线程安全:int volatile a = 0;
void fun() {
for (int j = 0; j < 100000; j++)
++a;
}
int main()
{
vector<thread> vec(10);
for (int i = 0; i < 10; ++i)
{
vec[i] = thread(fun);
}
for (auto& it : vec)
it.join();
cout << a << endl;
}首先,代码中定义了一个volatile
类型的整型变量a
,声明为volatile
后,说明对变量的访问是显示的,不能从编译器缓存中读取,必须从内存中读取,保证变量的正确性和可见性。然后定义了一个函数fun()
,该函数的作用是循环100000次,每次将变量a
的值加1,这个操作是在不同的线程中进行的,因此可能会存在并发问题。
接下来,在主函数中,创建一个包含10个元素的向量vec
,每个元素代表一个线程。在循环中,通过std::thread
类的构造函数创建一个线程并将其存储在vec
向量中。每个线程执行fun()
函数,将变量a
的值增加100000次。这个操作是在10个不同的线程中进行的,因此可能会产生并发问题。
为了保证对变量a
的访问安全和正确,主线程使用join()
函数等待所有的子线程都执行完毕后再输出变量a
的值。这样可以确保在输出变量a
之前,每一个子线程都已经完成了对变量a
的修改操作,不会产生并发问题。
最后,主线程输出变量a
的值,并且程序结束。
输出:
267423
对于原子操作,volatile能够保证线程安全atomic<int> volatile a = 0;
输出
1000000
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。