关于volatile

1.volatile 维基百科
  • volatile关键字用来阻止(伪)编译器认为的无法“被代码本身”改变的代码(变量/对象)进行优化。如在C语言中,
    volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

  • 在C语言中,编译器会根据你的代码进行优化,而volatile最直接的就是,告诉编译器不要优化这一个变量的运算过程。

2.volatile的优点
  • 优点:防止编译器对变量进行优化。
  • 为了提高效率,编译将变量值进行缓存,即把变量值从内存中读取进入寄存器中,每次访问变量时直接从寄存器中读取,volatile 就是告诉编译器不会优化这个变量,这个变量的值每次从内存中读取。
3.关于constvolatile同时修改变量
  • constvolatile可以同时修饰变量,语义上不矛盾。
  • const 表示被修饰的变量不能出现在赋值符号的左边。
  • volatile 表示使用变量时直接从内存取值。
  • 所以constvolatile同时修饰变量时互不影响其含义。
4.代码演示
  • 编写一个程序,线程间全局变量读写,模块设备初始化成功后进入系统。

  • (1)不使用volatile :

main.c

  1 
  2 #include <stdio.h>
  3 #include <unistd.h>
  4 
  5 extern const int device_init_flg;
  6 extern void device_init();
  7 
  8 int main(void)
  9 {
 10         device_init();
 11 
 12         while(device_init_flg != 1)
 13         {
 14                 sleep(1);
 15                 printf("wait device init..., status = %d\n", device_init_flg    );
 16         }
 17 
 18         printf("device init success...\n");
 19 
 20         printf("system start...\n");
 21 
 22         return 0;
 23 }

device.c

  1 
  2 #include <stdio.h>
  3 #include <pthread.h>
  4 #include <unistd.h>
  5 
  6 
  7 int device_init_flg = 0;
  8 
  9 void *pthread_func(void *argc)
 10 {
 11         sleep(5);
 12 
 13         device_init_flg = 1;
 14 
 15         printf("pthread device init status : %d\n", device_init_flg);
 16 }
 17 
 18 
 19 void device_init(void)
 20 {
 21         pthread_t tid = 0;
 22 
 23         pthread_create(&tid, NULL, pthread_func, NULL);
 24 }

不优化编译:

book@www.100ask.org:~/lzg/c$ ./a.out 
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
pthread device init status : 1
wait device init..., status = 1
device init success...
system start...

结果达到预期,主次线程间device_init_flg变量数值保持一致。
下面我们来增加 -O3 选项来进行优化编译:

book@www.100ask.org:~/lzg/c$ gcc -O3 main.c device.c -lpthread
book@www.100ask.org:~/lzg/c$ ./a.out 
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
pthread device init status : 1
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
^C

结果发现,次线程中device_init_flg变量值已经变为1了,但主线程中的device_init_flg变量值仍为0,并没有同步。这是因为编译时增加了优化等级处理,在main.c文件中,device_init_flg变量没有进行赋值,编译器就将device_init_flg的数值存储到寄存器中进行缓存,每次都到寄存器中读取device_init_flg的值。

  • 下面我们对device_init_flg变量增加volatile进行修饰。
    main.c
  2 #include <stdio.h>
  3 #include <unistd.h>
  4 
  5 extern const  volatile int device_init_flg;

device.c

  1 
  2 #include <stdio.h>
  3 #include <pthread.h>
  4 #include <unistd.h>
  5 
  6 
  7 volatile int device_init_flg = 0;

同样采用-O3选项进行优化编译:

book@www.100ask.org:~/lzg/c$ gcc -O3 main.c device.c -lpthread
book@www.100ask.org:~/lzg/c$ ./a.out 
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
wait device init..., status = 0
pthread device init status : 1
wait device init..., status = 1
device init success...
system start...

结果发现device_init_flg变量并没有被优化,主次线程中数据保持一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzg2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值