C++中的volatile关键字及其作用

2023-05-16 14:05:53 volatile 关键字 作用

volatile是C语言的一个关键字,该关键字的作用是保持内存的可见性

例子:

我们对2号信号进行了捕捉,当该进程收到2号信号时会将全局变量flag由0置1, 也就是说,在进程收到2号信号之前,该进程会一直处于死循环状态,直到收到2号信号时将flag置1才能够正常退出

#include <stdio.h>
#include <signal.h>
int flag = 0;
void handle(int signo)
{
	printf("收到一个 %d号信号\n",signo);
	flag = 1;
}
int main()
{
	signal(2,handle);//捕获2号信号
	while(!flag);
	printf("进程正常退出!\n");
	return 0;
}

上述代码中:main函数和handler函数是两个独立的执行流

判断一个数据为真为假 -> 逻辑运算 -> 需要CPU参与 ,常规情况下,需要从内存加载到CPU,然后CPU内部做判断,然后再把结果返回

而while循环是在main函数当中的,编译器发现:我们只对flag这个变量做检测,而不做修改, 编译器直接优化,把flag的值保存在寄存器中,直接在CPU检测

此时main函数在检测flag时只检测寄存器里面的值,而handler执行流只是将内存中flag的值置为1了,那么此时就算进程收到2号信号也不会跳出死循环

检验:在编译器优化级别较高的时候,就有可能将flag设置进寄存器里面

如何提高编译时的优先级呢? 在编译代码时携带 -O3 选项使得编译器的优化级别最高 

此时再运行该代码,就算向进程发生2号信号,该进程也不会终止

此时我们可以使用volatile关键字对flag变量进行修饰,告知编译器,对flag变量的任何操作都必须真实的在内存中进行,即保持了内存的可见性

#include <stdio.h>
#include <signal.h>
volatile int flag = 0;//告知编译器,对flag变量的任何操作都必须真实的在内存中进行
void handle(int signo)
{
	printf("收到一个 %d号信号\n",signo);
	flag = 1;
}
int main()
{
	signal(2,handle);//捕获2号信号
	while(!flag);
	printf("进程正常退出!\n");
	return 0;
}

此时就算我们编译代码时携带 -O3 选项,当进程收到2号信号将内存中的flag变量置1时,main函数执行流也能够检测到内存中flag变量的变化,进而跳出死循环正常退出

到此这篇关于c++中的volatile关键字及其作用的文章就介绍到这了,更多相关C++ volatile关键字内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章